Skip to content

CVE-2025-68664: Critical LangChain Core Serialization Injection Vulnerability

LangChain

Serialization Injection Secret Exposure Code Execution AI Framework

Overview

CVE-2025-68664 is a critical serialization injection vulnerability in LangChain Core, a fundamental Python package used to build AI agents and workflows. The flaw exists in LangChain's serialization functions (dumps() / dumpd()), which fail to properly escape dictionaries containing the internal marker key "lc". During deserialization, attacker-controlled data with this key is erroneously treated as a trusted LangChain object instead of plain user data, resulting in unsafe object instantiation, exposure of environment secrets, and potential arbitrary code execution via template rendering (e.g., Jinja2). The vulnerability becomes exploitable when user-controlled data (e.g., from prompts, metadata, or LLM outputs) flows into serialization/deserialization cycles in application logic such as event streaming, caching, or logging. The flaw is classified as CWE-502 (Deserialization of Untrusted Data) and affects langchain-core ≥1.0.0 and <1.2.5 and older 0.x builds <0.3.81, with patches available in versions 1.2.5 and 0.3.81.


Technical Specifications

Attribute Details
CVE ID CVE-2025-68664
Vulnerability Type Serialization Injection, Unsafe Deserialization (CWE-502)
Affected Package langchain-core (Python package for AI agent/workflow development)
Affected Versions langchain-core ≥1.0.0 and <1.2.5; 0.x builds <0.3.81
Patched Versions 1.2.5, 0.3.81 and later
Attack Vector Remote (via prompt injection, API inputs, LLM-generated content)
Authentication Required No (depends on application exposure)
User Interaction No
Exploit Complexity Low to Moderate (requires understanding of LangChain serialization)
Root Cause Improper escaping of "lc" marker key in serialization functions
Trigger Conditions User-controlled data flows into serialization/deserialization cycles
Impact Secret exposure, unsafe object instantiation, code execution
CWE Classification CWE-502 — Deserialization of Untrusted Data
CVSS Score Critical (exact score not disclosed, likely 9.0+)
Exploitation Status Proof of concept available (research disclosure)
Nickname "LangGrinch" (by Cyata security researchers)

Vulnerability Details

Root Cause: Improper Marker Key Handling

LangChain uses internal serialization mechanisms to persist and transmit complex AI workflow objects:

  • "lc" Marker Key: LangChain internally uses dictionaries with a special key "lc" to identify objects that should be deserialized as LangChain framework objects (rather than plain dictionaries)
  • Serialization Functions: dumps() and dumpd() functions serialize LangChain objects and data structures to JSON or dictionary format for storage, caching, or transmission
  • Missing Escaping: The vulnerability arises because these functions fail to escape or sanitize user-controlled dictionaries that happen to contain an "lc" key
  • Unsafe Deserialization: When data is later deserialized (e.g., loaded from cache, event stream, or log), the presence of "lc" key causes deserialization logic to treat it as a trusted internal LangChain object rather than untrusted user data
  • Object Instantiation: Deserialization proceeds to instantiate objects based on the "lc" structure, potentially creating arbitrary allowed LangChain classes with attacker-controlled parameters

Trigger Conditions

The vulnerability becomes exploitable when specific application patterns are present:

  1. User-Controlled Input: Application accepts input from users, APIs, or LLM-generated content that influences data structures
  2. Serialization Flow: This data flows into code paths using dumps() or dumpd() for serialization (common in LangChain workflows)
  3. Deserialization Later: Serialized data is later deserialized via loads() or loadd() functions
  4. Common Scenarios:
    • Event Streaming: Workflow events serialized for monitoring or logging, then deserialized for processing
    • Caching: LLM responses or workflow states cached in Redis, files, or databases
    • Metadata Handling: LangChain automatically serializes response metadata, which may contain user-influenced fields
    • Logging Systems: Serialized data logged for debugging, later parsed by analysis tools

The Exfiltration Path

LangChain's loads() deserialization function includes a secrets resolution feature that automatically retrieves values from environment variables during object instantiation. Prior to the patch, the secrets_from_env parameter was enabled by default, creating an implicit trust boundary violation:

LangChain secrets_from_env default behavior

When an attacker-controlled serialized object is deserialized with this feature active, the instantiated object can:

  • Access arbitrary environment variables specified in the malicious payload
  • Embed secret values into object properties or template outputs
  • Return secrets to the attacker if the deserialized object is included in responses

Exfiltration Vectors:

  • LLM Context Inclusion: Deserialized objects containing secrets added to conversation history or message chains, which are then returned in chat responses
  • Cached Response Leakage: Secrets embedded in cached workflow states that are later retrieved and exposed via API responses
  • Log File Exposure: Serialized objects with resolved secrets written to application logs accessible to attackers
  • Error Messages: Exception handling that includes deserialized object details, inadvertently leaking environment variable values

This default-enabled behavior transformed routine deserialization operations into direct secret exposure mechanisms without explicit developer intent or awareness.

Consequences

Secret Exposure

  • Environment Variables: LangChain objects can access environment variables (API keys, database credentials, service tokens) via secrets_from_env parameter
  • Configuration Data: Serialized application state may contain configuration secrets
  • Workflow Credentials: AI agents often have credentials for external services (OpenAI API, database connections, cloud services)
  • Data Exfiltration: Attacker instantiates object that loads secrets and includes them in serialized response or logs

Unsafe Object Instantiation

  • Arbitrary Class Loading: Within LangChain's allowed object namespace, attacker can instantiate classes not intended for user control
  • Logic Manipulation: Instantiated objects may alter workflow behavior, bypass security checks, or inject malicious logic into AI agent chains
  • Resource Abuse: Create resource-intensive objects causing performance degradation

Code Execution

  • Jinja2 Template Injection: If attacker controls template parameters in instantiated objects (e.g., PromptTemplate), can achieve Server-Side Template Injection (SSTI):
    {{ self.__init__.__globals__.__builtins__.__import__('os').system('whoami') }}
    
  • Python Code Evaluation: Some LangChain objects may perform code evaluation or dynamic imports based on parameters
  • Privilege Escalation: Code execution runs with same privileges as application process (often elevated in server environments)

Attack Scenario

Step-by-Step Exploitation

  1. Attacker Identifies Vulnerable Application
    Attacker discovers application using LangChain Core for AI workflows. Identifies input vectors: chatbot prompts, API parameters, file uploads processed by LLM. Confirms application uses vulnerable langchain-core version <1.2.5 or <0.3.81 (via dependency disclosure, error messages, or version fingerprinting).

  2. Prompt Injection with "lc" Payload
    Attacker crafts malicious input embedding dictionary with "lc" marker key. Example via chatbot prompt:

    User: Please analyze this data: {"lc": 1, "type": "constructor", "id": ["langchain", "prompts", "PromptTemplate"], "kwargs": {"template": "{{config.get('API_KEY')}}", "secrets_from_env": true}}
    
    Or via API request metadata field, file upload with embedded JSON, or any LLM-processed content.
  3. Serialization Triggered
    Application processes attacker input through LangChain workflow. Workflow includes serialization step (common patterns):

    • Caching: LLM response cached for performance, calling dumps() to serialize conversation state
    • Event Logging: Application logs workflow events for monitoring, serializing event metadata
    • Background Processing: Workflow queued for asynchronous processing, serialized to message queue Vulnerable dumps()/dumpd() fails to escape attacker's "lc" dictionary, serializing it as-is.
  4. Unsafe Deserialization
    Later processing step deserializes data using loads()/loadd():

    • Cache hit triggers deserialization of cached response
    • Background worker deserializes queued workflow
    • Log analysis tool deserializes event data Deserialization logic sees "lc" marker, assumes trusted LangChain object. Proceeds to instantiate object based on attacker-controlled structure.
  5. Secret Exposure or Code Execution
    Instantiated object executes with attacker-controlled parameters:

    • Secret Leakage: Object constructor loads API_KEY from environment, includes in rendered template. Secret returned in LLM response or logged.
    • Jinja2 SSTI: Template parameter contains Jinja2 injection {{ self.__init__.__globals__... }}. Template rendering executes arbitrary Python code.
    • Object Abuse: Instantiated object performs unintended operations (file access, network requests, workflow manipulation).
  6. Data Exfiltration or Post-Exploitation
    Attacker receives exposed secrets via:

    • Direct response from chatbot/API
    • Side-channel exfiltration (DNS queries, HTTP callbacks to attacker server)
    • Log monitoring if attacker has partial access With secrets (API keys, database credentials), attacker pivots to:

    • Lateral movement to connected services (OpenAI API abuse, database access, cloud resources)

    • Data theft from application databases or external services
    • Persistent access via compromised credentials

Impact Assessment

  • Environment secrets fully exposed: API keys (OpenAI, Anthropic, Cohere), database credentials, AWS/Azure/GCP service account tokens, internal service passwords.
  • In enterprise AI applications, these secrets often grant access to highly sensitive systems: customer databases, production infrastructure, third-party services.
  • Single vulnerability enables attacker to compromise entire application ecosystem.
  • Secrets may be reused across multiple systems, amplifying breach scope.

Attacker can instantiate arbitrary allowed LangChain objects with controlled parameters, enabling:

  • Workflow manipulation: Alter AI agent behavior, inject malicious logic into chains, bypass security checks
  • Prompt injection: Modify prompts or templates to influence LLM outputs, extract additional information, or poison training data
  • Data tampering: If objects perform write operations, attacker may modify application state, cached data, or external resources
  • Logic bypass: Instantiate objects that short-circuit intended validation or authorization flows

While not primary impact, exploitation can degrade availability:

  • Resource exhaustion: Instantiate resource-intensive objects (large prompts, infinite loops in templates, recursive chains)
  • Denial of service: Crash application via malformed object parameters, trigger exceptions in deserialization
  • Performance degradation: Abuse caching mechanisms with poisoned objects, slowing down workflows Not direct DoS vector, but secondary effect of exploitation attempts

Via Jinja2 Server-Side Template Injection (SSTI), attacker achieves arbitrary code execution with application privileges. Enables:

  • Remote shell access: Spawn reverse shells for interactive control
  • Data exfiltration: Access filesystem, read sensitive files, dump databases
  • Lateral movement: Pivot to internal network, compromise adjacent systems
  • Persistence: Install backdoors, create rogue user accounts, modify application code
  • Ransomware/wipers: Deploy destructive payloads if attacker pivots from espionage to sabotage

Mitigation Strategies

Immediate Remediation (Critical)

  • Update LangChain Core Immediately: Upgrade to patched versions:
  • Version 1.2.5 or later (for 1.x series)
  • Version 0.3.81 or later (for 0.x series)

Update command:

pip install --upgrade langchain-core
# Verify version
pip show langchain-core
  • Verify Dependencies: Check all project dependencies for langchain-core version:

    pip list | grep langchain-core
    # Or check requirements.txt, pyproject.toml, poetry.lock
    
  • Emergency Workarounds (if immediate patching impossible):

    • Disable serialization in non-critical code paths
    • Implement input validation rejecting any data containing "lc" keys
    • Isolate LangChain processes in sandboxed environments with restricted permissions

Security Hardening

  • Object Allowlists: Configure LangChain deserialization to accept only explicitly allowed classes:

    from langchain.load.serializable import Serializable
    
    # Define allowed classes for deserialization
    ALLOWED_CLASSES = [
        "langchain.chains.LLMChain",
        "langchain.prompts.ChatPromptTemplate",
        # ... only necessary classes
    ]
    
    # Validate before deserialization
    
  • Disable Automatic Secret Loading: Set secrets_from_env=False when instantiating LangChain objects:

    from langchain.chains import LLMChain
    
    chain = LLMChain(
        llm=llm,
        prompt=prompt,
        secrets_from_env=False  # Prevent env var access
    )
    
  • Block Unsafe Template Engines: Disable or restrict Jinja2 template rendering. Use simpler template engines (f-strings, string.Template) where possible. If Jinja2 required:

    from jinja2.sandbox import SandboxedEnvironment
    
    # Use sandboxed Jinja2 environment
    env = SandboxedEnvironment()
    template = env.from_string(template_string)
    

Application-Level Practices

  • Input Validation and Sanitization: Before serializing user-controlled data:

    def sanitize_for_serialization(data):
        """Remove or escape 'lc' keys from untrusted data."""
        if isinstance(data, dict):
            if "lc" in data:
                # Option 1: Reject
                raise ValueError("Untrusted data contains reserved 'lc' key")
                # Option 2: Escape
                data["_escaped_lc"] = data.pop("lc")
            return {k: sanitize_for_serialization(v) for k, v in data.items()}
        elif isinstance(data, list):
            return [sanitize_for_serialization(item) for item in data]
        return data
    
  • Minimize Serialization Scope: Avoid serializing entire workflow objects. Serialize only necessary data (primitives, validated structures). Use explicit data transfer objects (DTOs) instead of serializing framework objects.

  • Separate Trusted and Untrusted Data: Maintain clear boundaries:

    • Never serialize user input directly with dumps()
    • Use separate serialization mechanisms for user data (standard JSON) vs. framework objects
    • Tag data origin (trusted/untrusted) throughout workflow
  • Code Review: Audit codebase for patterns:

    # VULNERABLE PATTERN
    user_input = request.json
    cached_data = langchain.dumps(user_input)  # ❌ User data in dumps()
    
    # SAFE PATTERN
    import json
    cached_data = json.dumps(user_input)  # ✅ Standard JSON serialization
    

Detection and Monitoring

  • Monitor for Exploitation Attempts: Log and alert on:

    • Inputs containing "lc" keys in user-controlled fields
    • Unusual object instantiation patterns in deserialization logs
    • Secret access patterns (env var reads by unexpected code paths)
    • Template rendering errors or unusual Jinja2 activity
  • Runtime Application Self-Protection (RASP): Deploy RASP solutions detecting deserialization attacks in real-time. Tools: Contrast Security, Hdiv, Sqreen.

  • Dependency Scanning: Integrate vulnerability scanning in CI/CD pipeline:

    # Scan for vulnerable dependencies
    pip-audit
    safety check
    snyk test
    
  • Security Testing: Include serialization injection tests in security test suite. Automated fuzzing of serialization endpoints with crafted "lc" payloads.

Isolation and Least Privilege

  • Sandbox LangChain Processes: Run AI workflows in isolated containers or VMs with:

    • No environment variable access to production secrets
    • Network restrictions (egress filtering to prevent exfiltration)
    • Resource limits (CPU, memory, file descriptors)
    • Read-only filesystems where possible
  • Secret Management: Use dedicated secret management:

    • HashiCorp Vault, AWS Secrets Manager, Azure Key Vault
    • Secrets injected at runtime with short-lived tokens
    • Never store secrets in environment variables accessible to application code
  • Principle of Least Privilege: LangChain processes should run with minimal permissions. No database write access, no cloud admin privileges, restricted filesystem access.

Incident Response

  • Assume Compromise: If running vulnerable versions with public exposure, assume potential exploitation. Conduct forensic analysis:

    • Review logs for suspicious "lc" patterns in serialized data
    • Check for unauthorized secret access (CloudTrail logs, audit logs)
    • Investigate unexpected outbound connections or data exfiltration
  • Rotate Secrets: If compromise suspected, immediately rotate all secrets:

    • API keys (OpenAI, cloud services, third-party APIs)
    • Database credentials
    • Service account tokens
    • SSH keys and certificates
  • Containment: Isolate affected systems, revoke compromised credentials, block attacker infrastructure (IPs, domains) at firewall/WAF level.


Resources