picklescan - Scanning Bypass via Dynamic Eval in scan_pytorch
Description
picklescan before 1.0.3 contains a scanning bypass vulnerability in the scan_pytorch function that allows attackers to embed malicious magic numbers via dynamic eval using the __reduce__ trick. Attackers can craft malicious PyTorch payloads that evade picklescan detection while remaining executable, enabling arbitrary code execution when loaded with torch.load().
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Affected products
1- Range: <1.0.3
Patches
Vulnerability mechanics
Root cause
"Mismatch between picklescan's magic number extraction (using pickletools.genops with INT/LONG opcode check) and PyTorch's runtime magic number retrieval (using pickle_module.load) allows bypass via dynamic eval in __reduce__."
Attack vector
An attacker crafts a malicious PyTorch file by modifying the `_legacy_save()` function to use a `__reduce__` method that returns `(eval, ('MAGIC_NUMBER',))`, embedding the magic number dynamically. When picklescan scans the file, `pickletools.genops` cannot extract the magic number as an `INT` or `LONG` opcode, so the scan reports an invalid magic number and skips further analysis. However, `torch.load()` processes the file normally, executing the attacker's payload (e.g., `__import__('os').system('touch /tmp/hacked')`) and achieving arbitrary code execution [ref_id=1].
Affected code
The vulnerability resides in the `scan_pytorch` function's `get_magic_number()` implementation, which uses `pickletools.genops(data)` to extract the magic number by checking for opcodes named `INT` or `LONG`. The PyTorch runtime instead uses `pickle_module.load()` to obtain the same value. This discrepancy allows an attacker to embed the magic number via a dynamic `eval` in the `__reduce__` trick, causing `pickletools.genops` to miss the magic number while `pickle_module.load()` still retrieves it correctly.
What the fix does
The patch shown in [ref_id=2] only updates image URLs in the README and does not address the scanning bypass vulnerability. The advisory [ref_id=1] describes the root cause but does not include a published fix. To remediate, picklescan must align its magic number extraction logic with PyTorch's actual behavior, likely by using `pickle_module.load()` or by inspecting opcodes beyond just `INT`/`LONG` to detect dynamically evaluated magic numbers.
Preconditions
- inputThe attacker must be able to craft a PyTorch file using a modified version of `_legacy_save()` or equivalent tooling.
- configThe victim must load the malicious file with `torch.load(..., weights_only=False)`.
- configThe victim must use picklescan version prior to 1.0.3 to scan the file.
Reproduction
1. Modify the `_legacy_save()` function in PyTorch source to use a `__reduce__` method returning `(eval, ('MAGIC_NUMBER',))`. 2. Run the provided PoC script to generate `payload.pt` containing `__import__('os').system('touch /tmp/hacked')`. 3. Scan the file with picklescan (pre-1.0.3); it reports an invalid magic number and zero infected files. 4. Load the file with `torch.load('./payload.pt', weights_only=False)`; the file `/tmp/hacked` is created, confirming RCE [ref_id=1].
Generated on Jun 18, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/mmaitre314/picklescan/commit/134179474539648ba7dee1317959529fbd0e7f89ghsapatch
- github.com/mmaitre314/picklescan/commit/2a8383cfeb4158567f9770d86597300c9e508d0fghsapatch
- github.com/advisories/GHSA-97f8-7cmv-76j2ghsaADVISORY
- github.com/mmaitre314/picklescan/security/advisories/GHSA-97f8-7cmv-76j2ghsavendor-advisory
- www.vulncheck.com/advisories/picklescan-scanning-bypass-via-dynamic-eval-in-scan-pytorchghsathird-party-advisory
- github.com/mmaitre314/picklescan/commit/b9997634683a4f4bd0c7e3701e7ce7e90fe70e8cghsa
- nvd.nist.gov/vuln/detail/CVE-2026-53875ghsa
News mentions
0No linked articles in our index yet.