VYPR
Critical severityNVD Advisory· Published Feb 4, 2026· Updated Feb 4, 2026

Langroid has WAF Bypass Leading to RCE in TableChatAgent

CVE-2026-25481

Description

Langroid is a framework for building large-language-model-powered applications. Prior to version 0.59.32, there is a bypass to the fix for CVE-2025-46724. TableChatAgent can call pandas_eval tool to evaluate the expression. There is a WAF in langroid/utils/pandas_utils.py introduced to block code injection CVE-2025-46724. However it can be bypassed due to _literal_ok() returning False instead of raising UnsafeCommandError on invalid input, combined with unrestricted access to dangerous dunder attributes (__init__, __globals__, __builtins__). This allows chaining whitelisted DataFrame methods to leak the eval builtin and execute arbitrary code. This issue has been patched in version 0.59.32.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
langroidPyPI
< 0.59.320.59.32

Affected products

1

Patches

1
30abbc1a854d

Fix CVE-2025-46724 bypass in TableChatAgent sanitization (#966)

https://github.com/langroid/langroidPrasad ChalasaniFeb 1, 2026via ghsa
2 files changed · +34 0
  • langroid/utils/pandas_utils.py+11 0 modified
    @@ -237,6 +237,16 @@ def visit_Subscript(self, node: ast.Subscript) -> None:
                 raise UnsafeCommandError("subscript must be literal")
             self.generic_visit(node)
     
    +    # Attribute access
    +    def visit_Attribute(self, node: ast.Attribute) -> None:
    +        # Block dunder attributes to prevent access to __init__, __globals__, etc.
    +        if node.attr.startswith("__") and node.attr.endswith("__"):
    +            raise UnsafeCommandError(f"dunder attribute '{node.attr}' not allowed")
    +        # Block single underscore private attributes as well for defense in depth
    +        if node.attr.startswith("_") and node.attr not in WHITELISTED_DF_METHODS:
    +            raise UnsafeCommandError(f"private attribute '{node.attr}' not allowed")
    +        self.generic_visit(node)
    +
         # Method calls
         def visit_Call(self, node: ast.Call) -> None:
             if not isinstance(node.func, ast.Attribute):
    @@ -253,6 +263,7 @@ def visit_Call(self, node: ast.Call) -> None:
             for kw in node.keywords:
                 if kw.arg in BLOCKED_KW:
                     raise UnsafeCommandError(f"kwarg '{kw.arg}' is blocked")
    +            # Check numeric limits on literals; non-literals validated via generic_visit
                 _literal_ok(kw.value)
             for arg in node.args:
                 _literal_ok(arg)
    
  • tests/main/test_pandas_utils.py+23 0 modified
    @@ -40,6 +40,29 @@
             r"unexpected variable 'other_var'",
         ),
         (DEEP_EXPR, r"AST nesting too deep"),
    +    # CVE-2025-46724 bypass tests - dunder attribute access
    +    ("df.__init__", r"dunder attribute '__init__' not allowed"),
    +    ("df.__class__", r"dunder attribute '__class__' not allowed"),
    +    ("df.__globals__", r"dunder attribute '__globals__' not allowed"),
    +    ("df.__builtins__", r"dunder attribute '__builtins__' not allowed"),
    +    # CVE-2025-46724 bypass tests - private attribute access
    +    ("df._private", r"private attribute '_private' not allowed"),
    +    ("df._internal_method()", r"method '_internal_method' not permitted"),
    +    # CVE-2025-46724 bypass tests - dunder access via kwargs (the actual bypass vector)
    +    (
    +        "df.groupby(by=df.__init__)",
    +        r"dunder attribute '__init__' not allowed",
    +    ),
    +    (
    +        "df.groupby(by=df.__class__.__bases__)",
    +        r"dunder attribute '__.+__' not allowed",
    +    ),
    +    # Full PoC exploit payload - blocks on dunder attribute access
    +    (
    +        "df.add_prefix(\"__import__('os').system('ls')#\").T.groupby("
    +        "by=df.__init__.__globals__['__builtins__']['eval'])",
    +        r"dunder attribute '__.+__' not allowed",
    +    ),
     ]
     
     
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.