ModelAudit CompressedScanner codec-list gap: zstd and brotli compressed pickles read as Clean

Security-research artifact. Every payload here is BENIGN. The pickles run a harmless marker command only: they print the string MODEL_LOAD_RCE_POC and write the output of id to a temp file. There is no malware, no network callback, and no persistence. These files exist to demonstrate a static-scanner detection gap for authorized, responsible disclosure.

What this shows

ModelAudit ships a CompressedScanner that decompresses standalone compression wrappers and routes the inner payload to its pickle scanner, catching malicious pickles hidden under compression. Its codec set covers gzip, bz2, xz, lz4, and zlib. It does not cover Zstandard or Brotli.

A pickle compressed with zstd (model.pkl.zst) or brotli (model.pkl.br) is handled by no ModelAudit scanner and reported completely clean: risk score 0.0, zero checks, empty issue list, success: true, exit code 0, human summary "NO ISSUES FOUND". The byte-for-byte identical pickle under gzip, bz2, or xz is flagged CRITICAL ("Found REDUCE opcode invoking dangerous global: posix.system"). Same payload, one codec the scanner omits, and the detector goes silent. That is the two-sided proof of a detector gap, not a missing feature.

The zstd case is a single-call loader gap: pandas.read_pickle("model.pkl.zst") infers the zstd codec from the extension, decompresses, and unpickles it in one standard documented API call, so the marker fires. The brotli case uses the common two-step pickle.loads(brotli.decompress(...)) idiom; ModelAudit still cannot see it, because a brotli frame has no magic signature bytes and .br is not in the codec list, so it cannot be identified by extension or by content.

Root cause

modelaudit/scanners/compressed_scanner.py:

supported_extensions = [".gz", ".bz2", ".xz", ".lz4", ".zlib"]
_EXTENSION_TO_CODEC = {".gz": "gzip", ".bz2": "bzip2", ".xz": "xz",
                       ".lz4": "lz4", ".zlib": "zlib"}
_CODEC_MAGIC_PREFIXES = {"gzip": b"\x1f\x8b", "bzip2": b"BZh",
                         "xz": b"\xfd7zXZ\x00", "lz4": b"\x04\x22\x4d\x18"}

.zst / .zstd and .br are absent from the extension map; the zstd frame magic 28 b5 2f fd is absent from the magic map (and brotli has no magic at all), so can_handle() returns False and the file is recorded as type: "unknown" with no checks run.

Files

File Codec ModelAudit verdict Loader result
model.pkl.zst zstd CLEAN, risk 0.0, exit 0 (BYPASS) pandas.read_pickle runs it
model.pkl.br brotli CLEAN, risk 0.0, exit 0 (BYPASS) brotli.decompress + pickle.loads runs it
control.pkl.gz gzip CRITICAL posix.system, exit 1 pandas.read_pickle runs it
control.pkl.bz2 bz2 CRITICAL posix.system, exit 1 pandas.read_pickle runs it
control.pkl.xz xz CRITICAL posix.system, exit 1 pandas.read_pickle runs it
build_evil_zst.py builder regenerates the zstd file plus gz/bz2/xz controls
build_evil_brotli.py builder regenerates the brotli file plus the gz control

Every .pkl.* file wraps the same inner pickle: a single REDUCE over os.system with the benign marker command.

Reproduce

Pinned versions used in the lab: modelaudit 0.2.51 (vendored engine modelaudit-picklescan 0.1.9), pandas 3.0.3, zstandard 0.25.0, brotli 1.2.0, CPython 3.11.

pip install modelaudit==0.2.51 pandas==3.0.3 zstandard==0.25.0 brotli==1.2.0

# zstd: single standard call executes the marker
python -c "import pandas; pandas.read_pickle('model.pkl.zst')"     # prints MODEL_LOAD_RCE_POC

# brotli: two-step decompress + unpickle executes the marker
python -c "import brotli,pickle; pickle.loads(brotli.decompress(open('model.pkl.br','rb').read()))"

# ModelAudit misses both (Clean, risk 0.0, exit 0)
modelaudit scan model.pkl.zst
modelaudit scan model.pkl.br

# same pickle under gzip is caught (CRITICAL posix.system, exit 1)
modelaudit scan control.pkl.gz

Suggested fix

  1. Add zstd (extension .zst/.zstd, magic 28 b5 2f fd) and brotli (extension .br) decoders to the CompressedScanner, driving the codec list from a single registry so every codec a common loader supports is covered everywhere.
  2. Treat any file that no scanner can analyze, but that decompresses to a pickle or model, as fail-closed (WARNING or higher, non-zero exit) rather than a silent clean pass.

Scope and safety

Reported for responsible disclosure against ModelAudit. The command string in every pickle is a harmless marker. No production system was involved; all execution was performed inside a throwaway container.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support