VAITP Dataset

← Back to the dataset

CVE-2026-54769

Langroid: RCE via insecure `eval()` sandbox due to `__builtins__` access.

  • CVSS 10.0
  • CWE-94
  • Design Defects
  • Remote

Langroid is a framework for building large-language-model-powered applications. Versions prior to 0.65.2 are vulnerable to a critical Sandbox Escape leading to Remote Code Execution (RCE) in its `TableChatAgent` and `VectorStore` capabilities. When these agents evaluate LLM-generated tool messages with `full_eval=True`, they attempt to sandbox the execution by explicitly setting `locals` to an empty dictionary `{}` inside Python's `eval()` function. However, this relies on an incomplete understanding of Python's execution model. Because `__builtins__` is not explicitly scrubbed from the `globals` dictionary mapping, Python implicitly injects all built-ins during execution, granting full access to functions like `__import__('os').system()`. Since `TableChatAgent.pandas_eval()` executes external LLM outputs natively, this bypass permits any attacker providing prompt payload to achieve unauthenticated RCE on the host system. Version 0.65.2 patches the issue.

CVSS base score
10.0
Published
2026-07-10
OWASP
A03 Injection
Orthogonal defect classification
Checking
Code defect classification
Incorrect Check
Category
Design Defects
Subcategory
Command Injection
Accessibility scope
Remote
Impact
Arbitrary Code Execution
Affected component
Langroid
Fixed by upgrading
Yes

Solution

Upgrade to Langroid version 0.65.2 or later.

Vulnerable code sample

import pandas as pd

class VulnerableTableChatAgent:
    """
    A simplified representation of Langroid's TableChatAgent prior to version 0.65.2,
    demonstrating the vulnerability CVE-2026-54769.
    """
    def __init__(self):
        # The agent would typically manage a pandas DataFrame.
        self.df = pd.DataFrame({'user': ['Alice', 'Bob'], 'visits': [10, 22]})

    def pandas_eval(self, code_from_llm: str):
        """
        Simulates the vulnerable method that evaluates LLM-generated code.
        The attempt to sandbox execution by setting `locals` to an empty
        dictionary is incomplete and can be bypassed.
        """
        # This is the vulnerable call as described in the CVE.
        # `globals` is provided, but `__builtins__` is not scrubbed from it.
        # Python's `eval` function will implicitly add `__builtins__` to the
        # globals dictionary if it's missing, granting access to all built-in
        # functions, including the dangerous `__import__`.
        globals_for_eval = {"df": self.df}
        locals_for_eval = {}  # The failed sandbox attempt.

        try:
            # An attacker can provide a payload like:
            # "__import__('os').system('echo RCE achieved')"
            # This code will be executed by the host system.
            result = eval(code_from_llm, globals_for_eval, locals_for_eval)
            return result
        except Exception as e:
            return f"Error: {e}"

Patched code sample

def safe_pandas_eval(code_string: str, df=None, pd=None):
    """
    This function represents the patched code that fixes CVE-2026-54769.

    The vulnerability existed because Python's eval() function, when given a `globals`
    dictionary that does not contain a `__builtins__` key, will implicitly add
    the caller's `__builtins__`. This allows access to dangerous functions like
    `__import__`, leading to Remote Code Execution (RCE).

    The fix is to explicitly provide a `globals` dictionary to eval() that contains
    a `__builtins__` key with a restricted (or empty) dictionary. This prevents
    Python from adding the default, unsafe built-ins.
    """

    # The globals dictionary is defined with __builtins__ explicitly set to an
    # empty dictionary, effectively creating a sandbox.
    # Any safe, required modules like 'pd' (pandas) or variables like 'df'
    # are added explicitly to this safe dictionary.
    safe_globals = {
        "__builtins__": {},
        "pd": pd,
        "df": df,
    }

    try:
        # Calling eval() with the sanitized globals dictionary. An attempt to use
        # a dangerous built-in (e.g., `__import__('os').system('ls')`) will now
        # raise a NameError because `__import__` is not defined in the scope.
        return eval(code_string, safe_globals, {})
    except Exception as e:
        # The exception demonstrates that the malicious code was blocked.
        return f"Execution blocked: {e}"

Payload

__import__('os').system('touch /tmp/pwned')

Cite this entry

@misc{vaitp:cve202654769,
  title        = {{Langroid: RCE via insecure `eval()` sandbox due to `__builtins__` access.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-54769},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-54769/}}
}
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 ::