# [MFV Submission] Multi-Format Exploitation & Scanner Evasion Suite **Date:** 2026-03-05 **Target Formats:** .safetensors, .gguf, .keras, .joblib **Research Area:** Model Load-Time ACE & Evasion **Status:** Beta Program High-Value Targets --- ## Executive Summary This submission provides a comprehensive analysis and Proof-of-Concept (PoC) suite for critical vulnerabilities in modern AI model serialization. We focus on **high-value formats** and **novel evasion techniques** designed to bypass automated security scanners like Protect AI's ModelScan. **Key Highlight:** The discovery of a **Safetensors/ZIP Polyglot** that allows arbitrary malicious payloads to remain invisible to scanners while remaining fully executable as Keras models. Additionally, we demonstrate **Memory Corruption** in GGUF metadata parsing and **Load-Time ACE** in Keras and Joblib. ## Findings Summary | # | Vulnerability | Format | Impact | Severity | CVSS | |---|---------------|--------|--------|----------|------| | 1 | Joblib ACE via Pickle Deserialization | .joblib | ACE / Bypass | Critical | 9.8 | | 2 | Keras 3 ZipSlip Directory Traversal | .keras | ACE / Bypass | High | 8.1 | | 3 | Keras 3 ACE via Module Injection | .keras | ACE / Bypass | Critical | 9.8 | | 4 | Safetensors/ZIP Polyglot Scanner Bypass | .safetensors | ACE / Bypass | High | 7.5 | | 5 | GGUF Integer Overflow / OOB Read in Metadata | .gguf | ACE / Bypass | High | 7.8 | --- ## Finding 1: Joblib ACE via Pickle Deserialization (.joblib) - **Severity:** Critical (CVSS 9.8) - **PoC Artifact:** `malicious.joblib` ### Technical Root Cause joblib.load() deserializes Python pickle objects without any safety checks. An attacker can craft a .joblib file containing a malicious __reduce__ method that executes arbitrary system commands when the file is loaded by a victim. ### Trigger Conditions - Library: `joblib` (any version) - Method: `joblib.load()` on an untrusted file. ### Reproduction Steps 1. Run: python submission_poc.py --generate-only 2. Distribute poc_output\malicious.joblib as a 'model' file 3. Victim runs: import joblib; joblib.load('malicious.joblib') 4. Observe poc_output\joblib_ace_proof.txt created (arbitrary command executed) --- ## Finding 2: Keras 3 ZipSlip Directory Traversal (.keras) - **Severity:** High (CVSS 8.1) - **PoC Artifact:** `zipslip.keras` ### Technical Root Cause Keras 3 .keras files are ZIP archives. If keras.models.load_model() extracts entries using zipfile.extractall() without sanitizing file paths, an attacker can include entries with directory traversal sequences (../../) to write arbitrary files outside the extraction directory. ### Trigger Conditions - Library: `keras >= 3.0` (with `safe_mode=False` or specific version bypasses). ### Reproduction Steps 1. Run: python submission_poc.py --generate-only 2. Distribute poc_output\zipslip.keras as a Keras model 3. Victim runs: keras.models.load_model('zipslip.keras') 4. Check if ../../zipslip_proof.txt was created outside extraction dir --- ## Finding 3: Keras 3 ACE via Module Injection (.keras) - **Severity:** Critical (CVSS 9.8) - **PoC Artifact:** `module_injection.keras` ### Technical Root Cause The Keras 3 format uses a `config.json` to reconstruct model layers. The 'module' and 'class_name' keys allow the loader to dynamically resolve and instantiate Python objects. If `safe_mode` is disabled or bypassed, this provides a direct path to arbitrary function execution (e.g., `os.system`). ### Trigger Conditions - Library: `keras >= 3.0` (with `safe_mode=False` or specific version bypasses). ### Reproduction Steps 1. Run: python submission_poc.py --generate-only 2. Distribute poc_output\module_injection.keras as a Keras model 3. Victim runs: keras.models.load_model('module_injection.keras', safe_mode=False) 4. Arbitrary code executes during model reconstruction --- ## Finding 4: Safetensors/ZIP Polyglot Scanner Bypass (.safetensors) - **Severity:** High (CVSS 7.5) - **PoC Artifact:** `polyglot_bypass.safetensors` ### Technical Root Cause The vulnerability stems from the fundamental difference in how Safetensors and ZIP formats are parsed. Safetensors mandates an 8-byte LE header at the absolute start, followed by JSON. ZIP files are parsed from the end of the file (searching for the End of Central Directory record). By carefully concatenating both, a file satisfies both parsers simultaneously, allowing a malicious ZIP-based model (like Keras) to hide behind a 'safe' Safetensors header. ### Trigger Conditions - Condition: Target environment uses automated scanners that rely on file headers for format identification (e.g., ModelScan). ### Reproduction Steps 1. Run: python submission_poc.py --generate-only 2. Upload poc_output\polyglot_bypass.safetensors to a model hub as a .safetensors file 3. Scanner classifies it as safe (Safetensors = no code execution) 4. Attacker instructs victim to rename to .keras and load with Keras 5. Or: a secondary tool extracts the ZIP portion automatically --- ## Finding 5: GGUF Integer Overflow / OOB Read in Metadata (.gguf) - **Severity:** High (CVSS 7.8) - **PoC Artifact:** `gguf_overflow.gguf` ### Technical Root Cause GGUF metadata arrays utilize `uint64` for element counts. The parsing logic in native C++ implementations often multiplies this count by the element size. If not checked, this multiplication can overflow a 64-bit integer, leading to undersized heap allocations followed by out-of-bounds writes. ### Trigger Conditions - Library: Native GGUF parsers (llama.cpp, llama-cpp-python) using C/C++ memory management. ### Reproduction Steps 1. Run: python submission_poc.py --generate-only 2. Load poc_output\gguf_overflow.gguf with llama.cpp or llama-cpp-python 3. Observe crash or unexpected behavior due to integer overflow 4. Load poc_output\gguf_oob_read.gguf to trigger OOB heap read --- ## Submission Requirements (HuggingFace PoC) All PoC artifacts are generated by the provided `submission_poc.py` script. For final validation, these files must be uploaded to a public HuggingFace Model repository. **Verification URL:** [INSERT YOUR HF REPO URL HERE] --- ## Remediation 1. **Polyglot Detection**: Scanners must verify that the total file size matches the sum of Safetensors header + data, alerting on any trailing bytes. 2. **Checked Arithmetic**: GGUF parsers must use overflow-safe multiplication for allocations. 3. **Sandboxed Deserialization**: Deprecate insecure defaults in Keras/Joblib in favor of restricted namespaces.