# LangChain numexpr Evaluate Code Execution

- **Severity:** High
- **Signature ID:** `9c4b71e2-5a3d-4f28-b6e1-7d0a2c8f4531`
- **CVEs:** CVE-2023-39631
- **OWASP:** LLM05 (Improper Output Handling)

## Summary

LangChain versions before 0.0.308 let attackers run arbitrary Python code through the numexpr math library's evaluate() function, which is used by LangChain's math-solving chain. This rule catches the exploit only when it causes a new process to be spawned with a recognizable malicious code pattern on its command line.

## How the attack works

An attacker sends input to a LangChain application that gets routed to the numexpr evaluation feature, embedding Python code-execution primitives like __import__, os.system, subprocess calls, or class-hierarchy tricks (__subclasses__) inside what looks like a math expression. If this causes a child process to be spawned, the rule flags it in two ways: either a command line that touches the numexpr/LLMMathChain evaluation path while also containing a code-execution primitive, or a Python interpreter launched with a fully-formed sandbox-escape expression matching the known exploit shape. Once code runs, the attacker can execute system commands, read files, or steal credentials.

## Why it matters

An organisation running vulnerable LangChain applications can have arbitrary code executed on the host, leading to data theft, credential exposure, or further compromise of the system running the AI agent.

## What you can do

- Upgrade LangChain to 0.0.308 or later, or remove the numexpr dependency if not needed.
- Do not pass untrusted or user-supplied input directly into LangChain's math or expression-evaluation chains.
- Note that this rule only catches the exploit when it spawns a visible child process; an attacker's payload that stays entirely in-memory (reading files, opening network connections, or reading environment variables from within the same Python process) will not be caught here, so also monitor process behaviour, file reads, and outbound connections originating from the LangChain host process.
- Treat detections as high-confidence exploit attempts, but expect some benign matches from security testing, vulnerability reproduction, or static-analysis tooling that references the same code patterns.

## Known benign look-alikes

- Security engineer or AI coding agent reproducing CVE-2023-39631 in a sandbox, e.g. python -c "import numexpr; numexpr.evaluate(\"__import__('os').system('id')\")". This is a genuine detection of the exploit string and is reported, not blocked.
- Exploit fixtures or regression tests in a LangChain fork executed through a runner that places the payload in argv rather than in a test file.
- Semgrep / Bandit / CodeQL rule authoring where the --pattern argument contains __import__( next to numexpr (suppressed by filter_security_tooling).
- Source-code search for the vulnerable call site, e.g. rg "numexpr.evaluate" or grep -rn "__import__" (suppressed by filter_source_search).
- Dependency remediation such as pip install "langchain>=0.0.308" numexpr (suppressed by filter_pkg_mgmt).
- Advisory or changelog text quoted on a command line, identified by an embedded CVE-/GHSA- identifier (suppressed by filter_advisory_text).
- Legitimate pandas.eval / DataFrame.query workloads that use the numexpr engine. Not matched - the surface list requires an explicit numexpr import or numexpr.evaluate call token (engine="numexpr" alone does not match) and the primitive list deliberately excludes a bare eval( token.

## References

- https://nvd.nist.gov/vuln/detail/CVE-2023-39631
- https://owasp.org/Top10/A03_2021-Injection/

---
Source: https://www.netzilo.com/threats/langchain-numexpr-eval-rce
