# Langroid has WAF Bypass Leading to RCE in TableChatAgent

Langroid's pandas_eval WAF can be bypassed via dunder attribute chaining to reach __builtins__ eval, letting a prompt execute arbitrary shell commands.

- Payout: Research
- Severity: critical
- Program: Langroid
- Found by: Ka7arotto
- Disclosed: 2026-02-02
- CVE: CVE-2026-25481
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-x34r-63hx-w57f
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-x34r-63hx-w57f
- Tags: area:ai domain:ai impact:rce kind:research platform:ghsa sev:critical tech:llm tech:python technique:chained technique:incomplete-fix vuln:command-injection vuln:rce

**Target:** pandas_eval tool in TableChatAgent (Python library)
**Root cause:** The CVE-2025-46724 WAF's `_literal_ok()` returns False instead of raising UnsafeCommandError on invalid input, and dangerous dunder attributes (__init__, __globals__, __builtins__) remain accessible, so whitelisted DataFrame methods can be chained to reach the eval builtin.
**Steps:**
1. Craft expression chaining whitelisted DataFrame methods: `df.add_prefix("__import__('os').system('ls')#").T.groupby(by=df.__init__.__globals__['__builtins__']['eval'])`
2. Reach eval via `df.__init__.__globals__['__builtins__']['eval']`
3. Pass the add_prefix column name `__import__('os').system('ls')#` into eval, executing the shell command
4. Deliver via prompt instructing the agent to call pandas_eval with the expression
**How found:** Noticed the prior CVE-2025-46724 WAF's `_literal_ok()` returns False rather than raising on invalid input, and that dunder attributes were unrestricted, then chained whitelisted DataFrame methods to leak eval.
**Exploitation:** Attacker-controlled prompt to TableChatAgent instructs the LLM to call pandas_eval with the crafted expression; the WAF passes it, eval runs the injected column name, executing arbitrary shell commands on the server.
**Insight:** When auditing an eval/exec WAF, check whether validation failures return False instead of raising, and whether dunder chains (__init__.__globals__['__builtins__']) can reach builtins through otherwise-whitelisted object methods.

## Proof of concept (copied exactly from the original report)

**WAF bypass payload chaining dunder to eval**

```
df.add_prefix("__import__('os').system('ls')#").T.groupby(by=df.__init__.__globals__['__builtins__']['eval'])
```

