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, with what each is for, its license and its unsafe posture,
then every transitive crate with the direct
dependency that pulls it in. The published container image is built with
http, so it also carries the
opt-in dependencies. The
dependency policy behind these choices is in the repository’s
docs/DEPENDENCIES.md.
Memory-safety posture
Section titled “Memory-safety posture”- Safe Rust. Every workspace crate except the
exavbinary is#![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 library and no native
code generator. Compression (
flate2with the pure-Rustminiz_oxidebackend, and pure-Rust bzip2, xz, zstd and lzma crates) and crypto are pure Rust. There is no wasmtime, Cranelift, OpenSSL orringin the default binary. - A network server with no network crates. The ICAP server
adds no dependency: its framing, chunked decoding and
Encapsulatedparsing are written againststd, in a module that is#![forbid(unsafe_code)], so the parsers a hostile client reaches first are exav’s own. unsafein dependencies. Many dependencies useunsafeinternally: SIMD byte search and hashing, OS syscalls (the daemon), and buffer handling in some decoders that read scanned bytes (lzfse_rust,ruzstd,zip,tar,delharc,goblin). exav’s own crates contain none outside the daemon’slibccalls. The tables give a count per crate, and reducing it is on the roadmap.- Feature-gated capability. Optional features (
http-scan,http-update, individual formats) pull their dependencies only when enabled (see Feature flags). The network stack is opt-in, and it is the only thing that would link a crypto library that is not pure Rust (see Opt-in dependencies).
CLI & runtime (exav)
Section titled “CLI & runtime (exav)”The unsafe column is counted the same way as in
the transitive table.
| Crate | Purpose | License | unsafe uses |
|---|---|---|---|
clap |
Command-line argument parsing | MIT OR Apache-2.0 | none (forbid) |
serde_json |
JSON scan-report output | MIT OR Apache-2.0 | 13 |
walkdir |
Recursive directory traversal | Unlicense OR MIT | none |
regex |
--exclude / --include path filters |
MIT OR Apache-2.0 | 1 |
libc |
Syscall bindings for the prefork daemon (signals, resource limits) | MIT OR Apache-2.0 | 668 (FFI declarations) |
Spilling an oversized object to a temp file is not a dependency: it is
crates/exav/src/tmpfile.rs, a page of std::fs with the properties that matter
(O_CREAT|O_EXCL, so a planted symlink cannot be followed; mode 0600; delete
on drop). The ready-made crates reach the filesystem through rustix and
linux-raw-sys, which would add more unsafe than the rest of the tree.
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. The index the signature engine finds
its anchors with, which also serves as YARA’s atom prefilter, is exav’s own
code, not a dependency.
| Crate | Purpose | License | unsafe uses |
|---|---|---|---|
memchr |
Vectorized byte search | Unlicense OR MIT | 333 (SIMD) |
regex |
Linear-time regex (PCRE subsignatures, phishing allowlists) | MIT OR Apache-2.0 | 1 |
regex-automata / regex-syntax |
Linear-time (DoS-safe) regex engine + parser (YARA regexes, the atom prefilter’s required literals) | MIT OR Apache-2.0 | 55 / none (forbid) |
bit-set |
For the backtracking regex engine vendored in exav-core (below) | Apache-2.0 OR MIT | 2 |
goblin |
PE / ELF / Mach-O executable parsing | MIT | 34 |
md-5 / sha1 / sha2 |
Hash signatures (whole-file / section digests), and key derivation in decrypt |
MIT OR Apache-2.0 | 1 / 7 / 50 (CPU-feature detection, SIMD) |
crc32fast |
CRC-32 (the .exavdb trailer, YARA’s hash module, archive CRCs) |
MIT OR Apache-2.0 | 15 (SIMD) |
base64 |
Base64 decode (YARA base64 modifiers; uuencode, email, XDP and embedded payloads in exav-unpack) |
MIT OR Apache-2.0 | none (forbid) |
yara-x-parser |
YARA grammar/AST parser (the native engine’s front end) | BSD-3-Clause | 5 |
image |
Image decoding for fuzzy_img hashing, in exav-imagehash: PNG, GIF, BMP, WebP, ICO, PNM, QOI, DDS, farbfeld and HDR itself, JPEG and TIFF through its decoders vendored there (below) |
MIT OR Apache-2.0 | 6, plus its codecs below |
zune-jpeg / zune-core |
JPEG decoding for fuzzy image hashing (0.5.8, and 0.4.21 for JPEG-compressed TIFF), built without its SIMD features, which hold all of its unsafe |
MIT OR Apache-2.0 OR Zlib | none (forbid) / none (two versions of each resolve) |
png / gif |
image’s PNG and GIF decoders, required at the versions libclamav links (as are the JPEG and TIFF ones), which cargo install would not otherwise hold |
MIT OR Apache-2.0 | none (forbid) / none (forbid) |
hayro-jpeg2000 / hayro-jbig2 |
JPEG 2000 and JBIG2 decoding for fuzzy image hashing, in exav-render, built without their simd feature (fearless_simd); hayro-ccitt, below, is hayro-jbig2’s |
Apache-2.0 OR MIT | none (forbid) / none (forbid) |
fax / weezl / half / quick-error / bytemuck |
The vendored TIFF decoder’s: CCITT fax, LZW, 16-bit floats, error types, byte casts | MIT / MIT OR Apache-2.0 / MIT OR Apache-2.0 / MIT OR Apache-2.0 / Zlib OR Apache-2.0 OR MIT | none / none (forbid) / 84 / none / 323 |
tlsh2 |
TLSH fuzzy hashing | Apache-2.0 OR BSD-3-Clause | none |
rmp-serde / rmp / serde |
MessagePack encoding of the prebuilt .exavdb |
MIT / MIT / MIT OR Apache-2.0 | none (forbid) / 1 / 2 |
rustc-hash |
Fast hashing for internal maps (also in exav-pe-emu) |
Apache-2.0 OR MIT | none |
thiserror |
Error-type derive | MIT OR Apache-2.0 | none |
Some of exav is vendored source instead of dependencies, under its crates’
forbid(unsafe_code), with what changed from upstream in a README beside it:
- exav-core’s
src/fancy_regex/: fancy-regex 0.19.2 (MIT) with two fixes merged upstream after it, the backtracking engine for the PCRE subsignatures with lookaround, backreferences or atomic groups, under a step bound. Without the fixes it matches a byte above0x7Fas its UTF-8 encoding. - exav-render’s
src/image_codecs/, which exav-imagehash decodes through:image0.25.9’s JPEG and TIFF decoders and the decoder oftiff0.10.3 (MIT), so that zune-jpeg is built without its SIMD code, whichimageandtiffcannot turn off. - exav-imagehash’s
src/pillow.rs: Pillow 12.3.0’s resampler and grey conversions (MIT-CMU), ported for its imagehash preset. - exav-imagehash’s
src/dct.rs: rustdct 0.7.1’s DCT-II for power-of-two lengths (MIT), with bounds checks where upstream skips them withunsafe. Other lengths, which rustdct hands to rustfft and its SIMD code, go through a Bluestein FFT written there.
iced-x86 is not linked by any shipped binary. It is a dev-dependency of
exav-x86 only, the oracle its differential tests,
table generator and fuzz target check against.
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. Most of these read scanned bytes. The bzip2
decoder is not a dependency: it is vendored from bzip2-rs into
formats/bzip2_rs, with a fix for incompressible blocks, and is as
unsafe-free as the rest of the crate.
| Crate | Purpose | License | unsafe uses |
|---|---|---|---|
flate2 |
DEFLATE / gzip / zlib (pure-Rust miniz_oxide backend) |
MIT OR Apache-2.0 | 36 (no C zlib) |
deflate64 |
Deflate64 (ZIP method 9) | MIT | none (forbid) |
xz4rust |
XZ (.xz, ZIP method 95, DMG) |
MIT | 3 |
lzma-rust2 |
LZMA / LZMA2 (7z, lzip, ZIP method 14, SWF, NSIS, UPX, EGG) | Apache-2.0 | 14 |
ruzstd |
Zstandard (pure Rust) | MIT | 39 |
lzxd |
LZX (CAB) | MIT OR Apache-2.0 | none |
lzfse_rust |
LZFSE / LZVN (DMG) | MIT OR Apache-2.0 | 435 |
delharc |
LHA / LZH | MIT OR Apache-2.0 | 19 |
bitstream-io |
Bit-level readers for decoders | MIT OR Apache-2.0 | none (forbid) |
tar |
tar archives (xattr disabled, which drops its syscall crates) |
MIT OR Apache-2.0 | 26 |
zip |
ZIP container parsing | MIT | 32 |
cfb |
OLE2 / Compound File Binary (Office) | MIT | none |
encoding_rs |
the code pages of DXF and DWG drawings before 2007, Asian double-byte ones included (features dxf, dwg), built without simd-accel |
(Apache-2.0 OR MIT) AND BSD-3-Clause | 193 |
quick-xml |
OOXML / XML parsing | MIT | none (forbid) |
mail-parser |
MIME / email parsing | Apache-2.0 OR MIT | none (forbid) |
apfs / hfsplus |
DMG filesystem parsing | MIT | none |
ext4-view |
ext2/3/4 filesystem walking (virtual disks) | MIT OR Apache-2.0 | none (forbid) |
fatfs |
FAT12/16/32 cluster-chain walking | MIT | 11 |
lznt1 |
LZNT1 (NTFS compressed streams) | MIT | none (forbid) |
salzweg |
LZW (ZOO, Unix compress) |
MIT | none |
unshield |
InstallShield .z archives |
MIT | none |
tinyvec |
Inline vectors for the vendored bzip2 decoder | Zlib OR Apache-2.0 OR MIT | none (forbid) |
byteorder |
Byte-order reads | Unlicense OR MIT | 40 |
Cryptographic primitives (the decrypt feature)
Section titled “Cryptographic primitives (the decrypt feature)”Used only to decrypt encrypted members (see
Encryption support). These are
RustCrypto crates; their residual unsafe is
SIMD (AES-NI) and CPU-feature detection.
| Crate | Purpose | License | unsafe uses |
|---|---|---|---|
aes / cbc |
AES block cipher + CBC (ZIP, 7z, PDF, DMG, Office) | MIT OR Apache-2.0 | 60 / none |
des |
Triple DES (encrypted DMG key unwrap) | MIT OR Apache-2.0 | none |
hmac / pbkdf2 / digest |
Key derivation + MAC | MIT OR Apache-2.0 | none / none / none (forbid) |
constant_time_eq |
Constant-time comparison | CC0-1.0 OR MIT-0 OR Apache-2.0 | 2 |
stringprep |
Password normalization | MIT OR Apache-2.0 | none |
Opt-in dependencies (not in the default binary)
Section titled “Opt-in dependencies (not in the default binary)”Enabled only by http-scan (URL scanning, through exav-core) or
http-update (signature auto-update, through the
exav-update crate); http enables both. The
published container image is built with http; the release binaries are not.
| Crate | Purpose | License | Note |
|---|---|---|---|
ureq |
Minimal blocking HTTP(S) client | MIT OR Apache-2.0 | pulls ureq-proto, http, rustls → ring |
exav-update also uses sha2 and crc32fast, which the default build already
links. ring bundles C and assembly crypto; it is the one component exav can
pull that is not pure Rust, which is why HTTP is off by default.
Every transitive dependency
Section titled “Every transitive dependency”The tables above are the crates exav chose. The real supply chain is the whole
closure, so here is every remaining crate in the default exav build, with the
direct dependencies that pull it in. Count the packages against the current
lockfile with:
cargo tree -e no-dev -p exav --prefix none | sed 's/ (\*)$//' \ | awk '{print $1}' | sort -u | wc -lSeven of those are exav’s own workspace crates (exav, exav-core,
exav-unpack, exav-imagehash, exav-render, exav-pe-emu, exav-x86), and a few crates resolve at two
versions. None is a C library, a TLS stack or a code generator; syn, quote
and proc-macro2 are build-time proc-macro machinery, and autocfg,
rustc_version and semver run only in build scripts, so none of them has
runtime code in the binary.
The unsafe column counts occurrences of the unsafe keyword in each crate’s
shipped src/ (comments stripped; tests, benches and examples excluded) at the
version resolved when the table was written. Read it as surface to review, not as
risk. Most of it is in hashbrown and bytemuck, neither of which parses
scanned bytes, and in zerocopy (with its derive macro), which half pulls
in, and moxcms, which image does. There are
no raw-syscall binding crates: rustix and linux-raw-sys are kept out by
writing the spill file in-tree and by building tar
without xattr. Reproduce the counts with cargo geiger, or per crate with:
find ~/.cargo/registry/src/*/<crate>-<version>/src -name '*.rs' -print0 \ | xargs -0 sed 's://.*$::' | grep -cw unsafe| Crate | License | unsafe uses |
Pulled in by |
|---|---|---|---|
adler2 |
0BSD OR MIT OR Apache-2.0 | none (forbid) |
flate2, image, png, zip |
aho-corasick |
Unlicense OR MIT | 227 | regex, regex-automata, yara-x-parser |
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 | unshield |
ascii_tree |
MIT | none | yara-x-parser |
beef |
MIT OR Apache-2.0 | 26 | yara-x-parser |
bit-vec |
Apache-2.0 OR MIT | 4 | bit-set |
autocfg |
Apache-2.0 OR MIT | none | build-time: num-traits and its users |
bitflags |
MIT OR Apache-2.0 | 21 (two versions resolve: 19 + 2) | delharc, ext4-view, fatfs, image, png, yara-x-parser |
block-buffer |
MIT OR Apache-2.0 | 21 | digest, hmac, md-5, pbkdf2, sha1, sha2 |
block-padding |
MIT OR Apache-2.0 | none | aes, cbc, des |
bstr |
MIT OR Apache-2.0 | 39 | yara-x-parser |
byteorder-lite |
Unlicense OR MIT | 1 | image |
cfg-if |
MIT OR Apache-2.0 | none | crc32fast, flate2, half, image, md-5, png, sha1, sha2, tar, zip |
chrono |
MIT OR Apache-2.0 | 11 | delharc |
cipher |
MIT OR Apache-2.0 | none (forbid) |
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 |
cmov |
Apache-2.0 OR MIT | 25 | digest, hmac, md-5, pbkdf2, sha1, sha2 |
color_quant |
MIT | none | gif, image |
colorchoice |
MIT OR Apache-2.0 | none | clap |
const-oid |
Apache-2.0 OR MIT | 1 | digest, hmac, md-5, pbkdf2, sha1, sha2 |
countme |
MIT OR Apache-2.0 | 1 | yara-x-parser |
cpubits |
MIT OR Apache-2.0 | none | aes |
cpufeatures |
MIT OR Apache-2.0 | 11 | aes, sha1, sha2 |
crc |
MIT OR Apache-2.0 | none (forbid) |
ext4-view |
crc-catalog |
MIT OR Apache-2.0 | none (forbid) |
ext4-view |
crypto-common |
MIT OR Apache-2.0 | none (forbid) |
aes, cbc, des, digest, hmac, md-5, pbkdf2, sha1, sha2 |
ctutils |
Apache-2.0 OR MIT | none (forbid) |
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 | 5 | unshield |
fax_derive |
MIT | none | fax |
fdeflate |
MIT OR Apache-2.0 | none (forbid) |
image, png |
filetime |
MIT/Apache-2.0 | 9 | tar |
fnv |
Apache-2.0 / MIT | none | cfb, yara-x-parser |
hashbrown |
MIT OR Apache-2.0 | 751 (two versions resolve: 450 + 301) | mail-parser, yara-x-parser, zip |
hashify |
Apache-2.0 OR MIT | none | mail-parser |
hayro-ccitt |
Apache-2.0 OR MIT | none (forbid) |
hayro-jbig2 |
heck |
MIT OR Apache-2.0 | none (forbid) |
clap |
hybrid-array |
MIT OR Apache-2.0 | 37 | aes, cbc, des, digest, hmac, md-5, pbkdf2, sha1, sha2 |
iana-time-zone |
MIT OR Apache-2.0 | 212 | delharc |
image-webp |
MIT OR Apache-2.0 | none (forbid) |
image |
indexmap |
Apache-2.0 OR MIT | 12 | mail-parser, yara-x-parser, zip |
inout |
MIT OR Apache-2.0 | 30 | 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 |
lazy_static |
MIT OR Apache-2.0 | 2 | yara-x-parser |
log |
MIT OR Apache-2.0 | 6 | fatfs, 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; two versions resolve) |
flate2, image, png, zip |
moxcms |
BSD-3-Clause OR Apache-2.0 | 344 | image |
no_std_io2 |
Apache-2.0 OR MIT | 11 | bitstream-io, zip |
num-traits |
MIT OR Apache-2.0 | 1 | delharc, image, rmp, rmp-serde, yara-x-parser |
plain |
MIT/Apache-2.0 | 23 | goblin |
proc-macro2 |
MIT OR Apache-2.0 | 6 | apfs, clap, fax, goblin, half, hfsplus, lznt1, mail-parser, rmp-serde, serde, thiserror, yara-x-parser |
pxfm |
BSD-3-Clause OR Apache-2.0 | 224 | image |
qoi |
MIT/Apache-2.0 | none (forbid) |
image |
quote |
MIT OR Apache-2.0 | none | apfs, clap, fax, goblin, half, hfsplus, lznt1, mail-parser, rmp-serde, serde, thiserror, yara-x-parser |
rowan |
MIT OR Apache-2.0 | 55 | yara-x-parser |
rustc-hash |
Apache-2.0 OR MIT | none | a second version (1.x) for yara-x-parser |
rustc_version |
MIT OR Apache-2.0 | none | build-time: yara-x-parser |
same-file |
Unlicense/MIT | 3 | walkdir |
scroll |
MIT | 7 | goblin |
scroll_derive |
MIT | 1 | goblin |
semver |
MIT OR Apache-2.0 | 47 | build-time: yara-x-parser |
serde_core |
MIT OR Apache-2.0 | 2 | rmp-serde, serde, serde_json |
serde_derive |
MIT OR Apache-2.0 | none | rmp-serde, serde |
simd-adler32 |
MIT | 36 | flate2, image, png, zip |
strsim |
MIT | none (forbid) |
clap |
syn |
MIT OR Apache-2.0 | 152 (two versions resolve: 71 + 81) | apfs, clap, fax, goblin, half, hfsplus, lznt1, 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, lznt1, thiserror |
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, clap, fax, goblin, half, hfsplus, lznt1, 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 | 15 | cfb |
web-time |
MIT OR Apache-2.0 | none | cfb |
zerocopy |
BSD-2-Clause OR Apache-2.0 OR MIT | 482 | half |
zerocopy-derive |
BSD-2-Clause OR Apache-2.0 OR MIT | 807 | half |
zmij |
MIT | 70 | serde_json |
Verifying this yourself
Section titled “Verifying this yourself”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