PAIT-ARV-100: Archive Slip Vulnerabilities in Machine-Learning Model Packaging
Overview
Modern machine-learning workflows frequently distribute complex model architectures as compressed archive packages (such as .zip, .tar.gz, or bundled PyTorch checkpoints) containing weights, tokenizers, custom vocabularies, configuration schemas, and auxiliary C++ runtime binaries.
The PAIT-ARV-100 finding flags an Archive Slip (Zip Slip / Tar Slip) condition within model ingestion pipelines. When an AI training platform, MLOps orchestration runner, or model deployment service extracts untrusted archives without validating directory paths, crafted archive entries containing directory traversal sequences (such as ../../../../etc/cron.d/exploit) can overwrite critical operating system files, inject backdoors into shared libraries, or replace application code outside the target destination directory.
Technical Mechanics: How Archive Slip Operates in Python ML Workflows
Traditional archive extraction utilities in Python (zipfile and tarfile prior to Python 3.12 data filters) do not sanitize relative directory components by default. When an archive is extracted using naive methods, the extractor computes target file paths by concatenating the extraction root with the unvalidated archive entry name.
# Vulnerable extraction pattern in standard ML intake scripts
import tarfile
def load_model_archive(archive_path, target_dir):
with tarfile.open(archive_path, "r:gz") as tar:
# VULNERABLE: Extracts entries like '../../../../root/.ssh/authorized_keys'
tar.extractall(path=target_dir)
An attacker packages a model weight file alongside a malicious path traversal entry:
# Conceptual archive construction
tar -czvf malicious_model.tar.gz \
weights.bin \
config.json \
../../../../etc/cron.hourly/persist_backdoor
When the MLOps pipeline extracts malicious_model.tar.gz into /tmp/models/bert_v1/, the cron job is written directly to /etc/cron.hourly/, granting the adversary scheduled root code execution.
Key Threat Scenarios
- Scheduled Task Injection: Overwriting
/etc/cron.d/,/etc/profile.d/, or systemd user service directories on ML inference workers. - Library Hijacking (DLL / Shared Object Overwrite): Placing crafted
.soor.dllfiles in directory paths loaded ahead of standard system libraries (LD_LIBRARY_PATHinjection). - Application Source Poisoning: Overwriting Python source files (such as
app.pyorserve.py) within containerized inference microservices. - Symlink Manipulation: Extracting symlinks pointing to
/etc/shadowor sensitive configuration files, allowing subsequent read or write access through model serving APIs.
Hardened Extraction Implementation (Python Reference)
To neutralize PAIT-ARV-100, model intake services must implement strict path canonicalization, symlink blocking, and resource quotas before writing files to disk:
import os
import zipfile
def safe_extract_model_zip(zip_path: str, extract_to_dir: str, max_files: int = 1000, max_size_mb: int = 10240):
extract_to_dir = os.path.abspath(extract_to_dir)
total_uncompressed_bytes = 0
with zipfile.ZipFile(zip_path, 'r') as zf:
infolist = zf.infolist()
if len(infolist) > max_files:
raise ValueError(f"Archive exceeds maximum file count limit ({max_files})")
for member in infolist:
# 1. Block directory traversal and absolute paths
target_path = os.path.abspath(os.path.join(extract_to_dir, member.filename))
if not target_path.startswith(extract_to_dir + os.sep) and target_path != extract_to_dir:
raise SecurityError(f"Directory traversal attempt detected: {member.filename}")
# 2. Block symlinks and hardlinks
if (member.external_attr >> 16) & 0o120000 == 0o120000:
raise SecurityError(f"Symlink creation blocked: {member.filename}")
# 3. Prevent Zip Bomb decompression bombs
total_uncompressed_bytes += member.file_size
if total_uncompressed_bytes > max_size_mb * 1024 * 1024:
raise ValueError(f"Extracted size exceeds threshold ({max_size_mb} MB)")
zf.extract(member, extract_to_dir)
For Python 3.12+, always specify filter='data' when using tarfile.extractall():
with tarfile.open(archive_path, "r:gz") as tar:
tar.extractall(path=extract_to_dir, filter='data')
Remediation & Operational Hardening
- Isolate Intake Environments: Execute model unpacking in ephemeral sandbox containers with non-root service accounts and read-only root filesystems (
readOnlyRootFilesystem: true). - Cryptographic Model Provenance: Sign all internal model archives using Sigstore/Cosign and verify signatures before initiating extraction.
- Automated CI Validation: Integrate Eresus Sentinel into model deployment pipelines to catch PAIT-ARV-100 violations prior to staging promotion.
Frequently Asked Questions
Does PAIT-ARV-100 indicate that the model weights are malicious?
Not necessarily. The model weights might compute valid inference, but the container archive itself has been weaponized with auxiliary traversal paths.
Can running as a non-root user prevent Zip Slip?
Running as a non-root user reduces the attack surface by preventing writes to /etc/ or /usr/, but attackers can still overwrite user-owned application code, virtual environments, or SSH authorized keys.
What is the difference between Zip Slip and Pickling RCE?
Pickling RCE executes Python bytecode during memory deserialization, whereas Zip Slip abuses the filesystem unpacking mechanism to drop persistent executables on disk.
Security Validation
Have you tested this risk in your own system?
Eresus Security delivers real exploit evidence through penetration testing, AI agent security, and red team operations.
Request a pilot testRelated Services