Dependencies
exav is a security tool, so what it links is part of its threat model. This page
lists the dependencies of the shipped binary (exav, default features): the
direct ones first — what each is for, its license, and its unsafe
posture — then every transitive crate with the
direct dependency that pulls it in, so the full supply chain is on one page. The
dependency policy behind these choices is in the repository’s
docs/DEPENDENCIES.md.
Memory-safety posture
Section titled “Memory-safety posture”- Safe Rust by default. exav’s own scanning and extraction code is written in
safe Rust —
exav-coreandexav-unpackare#![forbid(unsafe_code)], so the crates that parse hostile input contain nounsafeof their own. - Pure Rust, no C, no JIT. The default build links no C libraries and no
native code generator. Compression (
flate2uses the pure-Rustminiz_oxidebackend, plus pure-Rust bzip2/xz/zstd/lzma crates) and crypto are all pure Rust. There is no wasmtime, no Cranelift, no OpenSSL, and noringin the default binary. - A network server with no network crates. The
ICAP server adds no dependency at all: its request framing,
chunked decoding and
Encapsulatedoffset parsing are written againststd, in a module that carries#![deny(unsafe_code)]— the parsers a hostile client reaches first are exav’s own code, not a transitive one. - Minimal, contained
unsafe. exav is not zero-unsafeoverall: a small number of dependencies useunsafeinternally, almost entirely for SIMD acceleration (byte search, hashing) and OS syscalls (the daemon). None of it is in exav’s own parsing logic, and driving the residual surface down is an explicit roadmap goal. - Feature-gated capability. Optional features (
http, individual formats) only pull their dependencies when enabled — see Feature flags. The network stack is opt-in: it is the only thing that would link a non-pure-Rust crypto library (see Opt-in dependencies).
The default binary resolves to 151 third-party crates in total: the 60 direct dependencies exav explicitly chose (below) plus 91 transitive ones.
CLI & runtime (exav)
Section titled “CLI & runtime (exav)”| Crate | Purpose | License | unsafe posture |
|---|---|---|---|
clap |
Command-line argument parsing | MIT OR Apache-2.0 | safe |
anyhow |
Error handling in the binary | MIT OR Apache-2.0 | safe |
serde_json |
JSON scan-report output | MIT OR Apache-2.0 | safe |
walkdir |
Recursive directory traversal | Unlicense OR MIT | safe |
regex |
Linear-time regex (CLI filters) | MIT OR Apache-2.0 | safe (SIMD via memchr/aho-corasick) |
libc |
Syscall bindings for the prefork daemon (signals, resource limits) | MIT OR Apache-2.0 | unsafe FFI declarations |
Spilling an oversized stream to a temp file is not a dependency: it is
exav/src/tmpfile.rs, a page of std::fs with the properties that matter
(O_CREAT|O_EXCL, so a pre-planted symlink cannot be followed; 0600; delete on
drop). The ready-made crates for it reach the filesystem through rustix and
linux-raw-sys, which would add more unsafe than the rest of the tree
combined — for a feature that never touches a scanned byte.
Core engine (exav-core)
Section titled “Core engine (exav-core)”The engine crate is #![forbid(unsafe_code)]; the unsafe noted below lives
inside these dependencies, not in exav.
| Crate | Purpose | License | unsafe posture |
|---|---|---|---|
daachorse |
Double-array Aho-Corasick automaton (the main pattern matcher) | MIT OR Apache-2.0 | perf-critical indexing |
aho-corasick |
Multi-pattern search (YARA atoms, prefilters) | Unlicense OR MIT | SIMD |
memchr |
Vectorized byte search | Unlicense OR MIT | SIMD |
regex-automata / regex-syntax |
Linear-time (DoS-safe) regex engine + parser | MIT OR Apache-2.0 | via memchr |
fancy-regex |
Backtracking regex for wildcard-signature verification | MIT | safe |
goblin |
PE / ELF / Mach-O executable parsing | MIT | safe |
iced-x86 |
Not linked by any shipped binary. A dev-dependency of exav-x86 only, where it is the oracle its differential tests, table generator and fuzz target check against |
MIT | handler dispatch through raw pointers, and integer-to-enum transmutes on table indices |
md-5 / sha1 / sha2 |
Hash signatures (whole-file / section digests) | MIT OR Apache-2.0 | minimal (CPU-feature detection) |
crc32fast |
CRC32 | MIT OR Apache-2.0 | SIMD |
base64 |
Base64 decode (embedded payloads, YARA) | MIT OR Apache-2.0 | safe |
bstr |
Byte-string utilities (YARA engine) | MIT OR Apache-2.0 | safe |
yara-x-parser |
YARA grammar/AST parser (the native engine’s front end) | BSD-3-Clause | safe |
image |
Icon/image decoding for fuzzy image hashing | MIT OR Apache-2.0 | some, in codec paths |
rustdct / transpose |
DCT for perceptual image hashing | MIT OR Apache-2.0 | safe |
tlsh2 |
TLSH fuzzy hashing | Apache-2.0 OR BSD-3-Clause | safe |
rmp-serde / serde |
MessagePack (de)serialization of the prebuilt .exavdb |
MIT / MIT OR Apache-2.0 | safe |
thiserror |
Error-type derive | MIT OR Apache-2.0 | safe |
Extraction & decompression (exav-unpack)
Section titled “Extraction & decompression (exav-unpack)”Also #![forbid(unsafe_code)]. The decoders are pure-Rust; there is no C
compression library in the tree.
| Crate | Purpose | License | unsafe posture |
|---|---|---|---|
flate2 |
DEFLATE / gzip / zlib (pure-Rust miniz_oxide backend) |
MIT OR Apache-2.0 | safe (no C zlib) |
deflate64 |
Deflate64 (ZIP method 9) | MIT | none — forbid |
bzip2-rs |
bzip2 (pure Rust) | MIT OR Apache-2.0 | safe |
xz4rust |
XZ / LZMA (pure Rust) | MIT | safe |
lzma-rust2 |
LZMA / LZMA2 (7z) | Apache-2.0 | safe |
ruzstd |
Zstandard (pure Rust) | MIT | safe |
lzxd |
LZX (CAB) | MIT OR Apache-2.0 | safe |
lzfse_rust |
LZFSE / LZVN (DMG) | MIT OR Apache-2.0 | safe |
delharc |
LHA / LZH | MIT OR Apache-2.0 | safe |
bitstream-io |
Bit-level readers for decoders | MIT OR Apache-2.0 | safe |
tar |
tar archives (xattr disabled — drops syscall unsafe) |
MIT OR Apache-2.0 | safe |
zip |
ZIP container parsing | MIT | safe |
cfb |
OLE2 / Compound File Binary (Office) | MIT | safe |
quick-xml |
OOXML / XML parsing | MIT | safe |
mail-parser |
MIME / email parsing | Apache-2.0 OR MIT | safe |
apfs / hfsplus |
DMG filesystem parsing | MIT | safe |
ext4-view |
ext2/3/4 filesystem walking (virtual disks) | MIT OR Apache-2.0 | none — forbid |
fatfs |
FAT12/16/32 cluster-chain walking | MIT | 13 |
lznt1 |
LZNT1 (NTFS compressed streams) | MIT | none — forbid |
salzweg |
LZW (ZOO, Unix compress) |
MIT | none |
unshield |
InstallShield .z archives |
MIT | none |
byteorder / bincode |
Byte-order + binary (de)serialization | Unlicense OR MIT / MIT | safe |
Cryptographic primitives (the decrypt feature)
Section titled “Cryptographic primitives (the decrypt feature)”Used only to decrypt encrypted archive members. These are RustCrypto
crates; their residual unsafe is confined to SIMD/CPU-feature detection.
| Crate | Purpose | License | unsafe posture |
|---|---|---|---|
aes / cbc |
AES block cipher + CBC (ZIP/7z/DMG) | MIT OR Apache-2.0 | minimal (CPU-feature detection) |
des |
DES (legacy archive encryption) | MIT OR Apache-2.0 | safe |
hmac / pbkdf2 / digest |
Key derivation + MAC | MIT OR Apache-2.0 | safe |
constant_time_eq |
Constant-time comparison | CC0-1.0 OR MIT-0 OR Apache-2.0 | safe |
stringprep |
Password normalization | MIT OR Apache-2.0 | safe |
Opt-in dependencies (not in the default binary)
Section titled “Opt-in dependencies (not in the default binary)”Enabled only by the http feature (URL scanning / signature auto-update),
handled by the separate exav-update crate:
| Crate | Purpose | License | Note |
|---|---|---|---|
ureq |
Minimal blocking HTTP(S) client | MIT OR Apache-2.0 | pulls rustls → ring |
ring bundles C/assembly crypto — it is the one non-pure-Rust component exav can
pull, which is exactly why HTTP is off by default. Builds that don’t need
network fetch never link it.
Every transitive dependency
Section titled “Every transitive dependency”The tables above are the crates exav chose. Those crates pull in their own
dependencies, and a security tool’s real supply chain is the whole closure — so
here it is: every remaining crate in the default exav build, with the
direct dependency (or dependencies) that pulls it in.
The default exav build resolves to 159 packages, five of which are
exav’s own workspace crates (exav, exav-core, exav-unpack,
exav-pe-emu, exav-x86). bitflags, hashbrown and rustc-hash each resolve
at two major versions, so the count of distinct projects is lower still. Check
it against the current lockfile with:
cargo tree -e no-dev -p exav --prefix none | sed 's/ (\*)$//' \ | awk '{print $1}' | sort -u | wc -lNothing here is a C library, a TLS stack, or a code generator. syn, quote and
proc-macro2 are build-time proc-macro machinery and contribute no runtime code
to the binary.
35 of the 94 packages contain no unsafe at all, 17 of those enforcing it with a
crate-root #![forbid(unsafe_code)]. The unsafe uses column counts occurrences
of the unsafe keyword in each crate’s shipped src/ (comments stripped; tests,
benches and examples excluded) at the exact version this build resolves. Read it
as surface area to review, not as risk: a count is not a defect, and the
concentration is unsurprising — rustfft (SIMD butterflies, reached only through
the perceptual image hash), hashbrown and bytemuck are 2,496 of the 3,490
occurrences in this table, and none of them sits on a path that parses scanned
bytes. There are no raw-syscall binding crates here at all — the two that would
otherwise dominate the count, rustix and linux-raw-sys, are kept out by
writing the daemon’s spill file in-tree and by building
tar without xattr. Reproduce the count with cargo geiger, or per crate
with:
grep -rc '\bunsafe\b' ~/.cargo/registry/src/*/<crate>-<version>/src/| Crate | License | unsafe uses |
Pulled in by |
|---|---|---|---|
adler2 |
0BSD OR MIT OR Apache-2.0 | none — forbid |
flate2, image, zip |
anstream |
MIT OR Apache-2.0 | 3 | clap |
anstyle |
MIT OR Apache-2.0 | 1 | clap |
anstyle-parse |
MIT OR Apache-2.0 | 3 | clap |
anstyle-query |
MIT OR Apache-2.0 | 1 | clap |
arraydeque |
MIT/Apache-2.0 | 77 | explode |
ascii_tree |
MIT | none | yara-x-parser |
beef |
MIT OR Apache-2.0 | 26 | yara-x-parser |
bit-set |
Apache-2.0 OR MIT | 2 | fancy-regex |
bit-vec |
Apache-2.0 OR MIT | 4 | fancy-regex |
bitflags |
MIT OR Apache-2.0 | 2 | delharc, image, yara-x-parser |
block-buffer |
MIT OR Apache-2.0 | 4 | digest, hmac, md-5, pbkdf2, sha1, sha2 |
block-padding |
MIT OR Apache-2.0 | 1 | aes, cbc, des |
bytemuck |
Zlib OR Apache-2.0 OR MIT | 318 | image |
cfg-if |
MIT OR Apache-2.0 | none | aes, bzip2-rs, crc32fast, flate2, image, md-5, sha1, sha2, tar, zip |
chrono |
MIT OR Apache-2.0 | 11 | delharc |
cipher |
MIT OR Apache-2.0 | 2 | aes, cbc, des |
clap_builder |
MIT OR Apache-2.0 | none — forbid |
clap |
clap_derive |
MIT OR Apache-2.0 | none — forbid |
clap |
clap_lex |
MIT OR Apache-2.0 | 6 | clap |
color_quant |
MIT | none | image |
colorchoice |
MIT OR Apache-2.0 | none | clap |
countme |
MIT OR Apache-2.0 | 1 | yara-x-parser |
cpufeatures |
MIT OR Apache-2.0 | 9 | aes, sha1, sha2 |
crc |
MIT OR Apache-2.0 | none — forbid |
ext4-view |
crc-catalog |
MIT OR Apache-2.0 | none — forbid |
crc |
crypto-common |
MIT OR Apache-2.0 | none — forbid |
aes, cbc, des, digest, hmac, md-5, pbkdf2, sha1, sha2 |
either |
MIT OR Apache-2.0 | 2 | yara-x-parser |
equivalent |
Apache-2.0 OR MIT | none | mail-parser, yara-x-parser, zip |
explode |
MIT | 6 | unshield |
fdeflate |
MIT OR Apache-2.0 | none — forbid |
image |
filetime |
MIT/Apache-2.0 | 9 | tar |
fnv |
Apache-2.0 / MIT | none | cfb, yara-x-parser |
generic-array |
MIT | 78 | aes, cbc, des, digest, hmac, md-5, pbkdf2, sha1, sha2 |
gif |
MIT OR Apache-2.0 | none — forbid |
image |
hashbrown |
MIT OR Apache-2.0 | 759 (two versions resolve: 454 + 305) | mail-parser, yara-x-parser, zip |
hashify |
Apache-2.0 OR MIT | none | mail-parser |
heck |
MIT OR Apache-2.0 | none — forbid |
clap |
iana-time-zone |
MIT OR Apache-2.0 | 212 | delharc |
indexmap |
Apache-2.0 OR MIT | 11 | mail-parser, yara-x-parser, zip |
inout |
MIT OR Apache-2.0 | 22 | aes, cbc, des |
is_terminal_polyfill |
MIT OR Apache-2.0 | none | clap |
itertools |
MIT OR Apache-2.0 | 10 | yara-x-parser |
itoa |
MIT OR Apache-2.0 | 13 | serde_json |
jpeg-decoder |
MIT OR Apache-2.0 | 16 | image |
lazy_static |
MIT OR Apache-2.0 | 2 | iced-x86, yara-x-parser |
log |
MIT OR Apache-2.0 | 6 | goblin |
logos |
MIT OR Apache-2.0 | 18 | yara-x-parser |
logos-codegen |
MIT OR Apache-2.0 | 4 | yara-x-parser |
logos-derive |
MIT OR Apache-2.0 | none | yara-x-parser |
miniz_oxide |
MIT OR Zlib OR Apache-2.0 | none — forbid |
flate2, image, zip |
no_std_io2 |
Apache-2.0 OR MIT | 11 | bitstream-io |
num-complex |
MIT OR Apache-2.0 | 2 | rustdct |
num-integer |
MIT OR Apache-2.0 | none | rustdct, transpose |
num-traits |
MIT OR Apache-2.0 | 1 | delharc, image, rmp-serde, rustdct, transpose, yara-x-parser |
plain |
MIT/Apache-2.0 | 23 | goblin |
png |
MIT OR Apache-2.0 | none — forbid |
image |
primal-check |
MIT OR Apache-2.0 | none | rustdct |
proc-macro2 |
MIT OR Apache-2.0 | 6 | apfs, bincode, clap, goblin, hfsplus, mail-parser, rmp-serde, serde, thiserror, yara-x-parser |
quote |
MIT OR Apache-2.0 | none | apfs, bincode, clap, goblin, hfsplus, mail-parser, rmp-serde, serde, thiserror, yara-x-parser |
rmp |
MIT | 1 | rmp-serde |
rowan |
MIT OR Apache-2.0 | 55 | yara-x-parser |
rustc-hash |
Apache-2.0 OR MIT | none | yara-x-parser |
rustfft |
MIT OR Apache-2.0 | 1419 | rustdct |
same-file |
Unlicense/MIT | 3 | walkdir |
scroll |
MIT | 7 | goblin |
scroll_derive |
MIT | 1 | goblin |
serde_core |
MIT OR Apache-2.0 | 2 | bincode, rmp-serde, serde, serde_json |
serde_derive |
MIT OR Apache-2.0 | none | bincode, rmp-serde, serde |
simd-adler32 |
MIT | 36 | flate2, image, zip |
strength_reduce |
MIT OR Apache-2.0 | none | rustdct, transpose |
strsim |
MIT | none — forbid |
clap |
subtle |
BSD-3-Clause | 2 | digest, hmac, md-5, pbkdf2, sha1, sha2 |
syn |
MIT OR Apache-2.0 | 71 | apfs, bincode, clap, goblin, hfsplus, mail-parser, rmp-serde, serde, thiserror, yara-x-parser |
text-size |
MIT OR Apache-2.0 | none — forbid |
yara-x-parser |
thiserror-impl |
MIT OR Apache-2.0 | 1 | apfs, hfsplus, thiserror |
tiff |
MIT | 2 | image |
tinyvec |
Zlib OR Apache-2.0 OR MIT | none — forbid |
bzip2-rs, stringprep |
tinyvec_macros |
MIT OR Apache-2.0 OR Zlib | none — forbid |
bzip2-rs, stringprep |
twox-hash |
MIT | 72 | ruzstd |
typed-path |
MIT OR Apache-2.0 | 32 | zip |
typenum |
MIT OR Apache-2.0 | none — forbid |
aes, cbc, des, digest, hmac, md-5, pbkdf2, sha1, sha2 |
unicode-bidi |
MIT OR Apache-2.0 | 1 | stringprep |
unicode-ident |
(MIT OR Apache-2.0) AND Unicode-3.0 | 2 | apfs, bincode, clap, goblin, hfsplus, mail-parser, rmp-serde, serde, thiserror, yara-x-parser |
unicode-normalization |
MIT OR Apache-2.0 | 5 | stringprep |
unicode-properties |
MIT/Apache-2.0 | none | stringprep |
utf8parse |
Apache-2.0 OR MIT | 1 | clap |
uuid |
Apache-2.0 OR MIT | 9 | cfb |
web-time |
MIT OR Apache-2.0 | none | cfb |
weezl |
MIT OR Apache-2.0 | none — forbid |
image |
zmij |
MIT | 74 | serde_json |
Verifying this yourself
Section titled “Verifying this yourself”Nothing here has to be taken on trust — regenerate the tables above and check them:
# Direct + transitive dependencies of the default binary, with licenses.# --no-dedupe (or --invert <crate>) is what shows every "pulled in by" edge:cargo tree -p exav -e normal --no-dedupe --format "{p} {l}"
# Audit advisories, bans, and the license allowlist (also run in CI):cargo deny checkcargo audit