Was die SSTI technisch ist
LiteLLM bietet seit Version 1.80.5 einen Endpunkt POST /prompts/test, der Prompt-Templates an verschiedene Modelle ausspielt und die Render-Ergebnisse zurückgibt — als Werkzeug für Prompt-Engineers, die ihre Templates gegen reale LLM-Backends durchprobieren wollen. Der Render passiert in Jinja2, der Standard-Template-Engine der Python-Welt. Das ist sinnvoll, weil Prompts in der Praxis Variablen einsetzen müssen ({{ user_input }}, {{ context }}). Es ist nur dann sinnvoll, wenn der Render in einer Sandbox geschieht.
Jinja2 stellt dafür SandboxedEnvironment zur Verfügung — eine Variante des Standard-Environments, die Attribut-Zugriffe auf Python-interne Methoden blockiert und Calls auf bekannte Eskalations-Pfade (__class__, __mro__, __subclasses__(), __globals__) verhindert. Genau diese Sandbox fehlt in /prompts/test der Versionen 1.80.5 bis 1.83.6. Die klassische Jinja2-SSTI-Eskalations-Kette funktioniert deshalb out-of-the-box: ein paar Zeilen {{ ''.__class__.__mro__[1].__subclasses__() }} reichen, um die Liste aller geladenen Python-Subklassen zu erhalten — inklusive subprocess.Popen.
Der Endpunkt prüft, dass der Caller einen gültigen Proxy-API-Key trägt. Das ist genau die Sorte „Authentifizierung, aber nicht wirklich Autorisierung“, die in API-Gateway-Designs regelmäßig schiefgeht: Jeder Mitarbeitende, jede LLM-Backend-Integration, jede Test-Pipeline mit eigenem API-Key kann den Endpunkt ansprechen. In einer realistischen LiteLLM-Installation hat ein normaler Anwendungs-Key Zugriff auf /prompts/test, weil es ein read_only-Pfad in der Default-Permission-Map ist.
Warum die Zwei-Wochen-Linie wichtiger ist als die einzelne Lücke
Wer nur die einzelne Lücke betrachtet, sieht ein bekanntes SSTI-Pattern in einem populären Open-Source-Projekt. Wer die Zwei-Wochen-Linie betrachtet, sieht ein strukturelles Muster in der LiteLLM-Codebase. 23. April: Pre-Auth SQL Injection in der Key-Verifikation. Der Endpunkt, der Authentifizierung herstellen soll, leakt Datenbank-Inhalte (CVE-2026-42208, CVSS 9.3, KEV-Eintrag). 7. Mai: Post-Auth SSTI in einem unsandboxed Template-Render. Der Endpunkt, der hinter Authentifizierung sicher sein sollte, gibt Code-Execution.
Beide Lücken liegen im selben Subsystem — der Proxy-API-Schicht — und beide treffen exakt dort, wo LiteLLM-Operatoren historisch wenig Aufmerksamkeit investiert haben: nicht in den /chat/completions-Pfad, sondern in die administrativen Tooling-Endpunkte. Die operative Lehre ist nicht „LiteLLM ist unsicher“, sondern „der /prompts/*- und der Key-Management-Subraum verdienen die gleiche Sicherheitsdisziplin wie der eigentliche Inferenz-Pfad“.
Wer ist betroffen
Direkt betroffen sind alle LiteLLM-Proxy-Installationen in den Versionen 1.80.5 bis einschließlich 1.83.6 — also jede LiteLLM-Installation, die seit etwa Mitte März 2026 frisch deployed oder seither aktualisiert wurde, ohne den Sprung auf 1.83.7-stable zu machen. Die Open-Source-Variante ist betroffen; die Enterprise-Variante ist es ebenfalls (sie teilt die Codebase).
Wer LiteLLM hinter einem zusätzlichen API-Gateway betreibt (Kong, Tyk, AWS API Gateway, Cloudflare Workers), hat einen sekundären Schutzring: Wenn dieses Gateway Path-basierte Allowlisting fährt und /prompts/test nicht freischaltet, ist der direkte Angriff blockiert. Wer LiteLLM in einem Mehrmandanten-Setup betreibt (ein Proxy für mehrere Kunden, Teams oder Anwendungen mit jeweils eigenen API-Keys), hat das größte operative Risiko: jeder dieser Keys kann den Endpunkt ansprechen, und ein kompromittierter Anwendungs-Key gibt RCE auf dem Proxy-Prozess. Wer LiteLLM als MCP-Server-Backend einsetzt, hat einen besonderen Eskalations-Pfad: ein Prompt-Injection-Angriff auf den MCP-Konsumenten kann strukturell darauf abzielen, einen Aufruf gegen /prompts/test mit präpariertem Template zu generieren.
Mitigation und Sofortmaßnahmen
Die saubere Reihenfolge ist: erstens Versionsprüfung am Proxy (curl -s litellm-proxy/health/litellm-versions | jq '.litellm_version'); zweitens Update auf 1.83.7-stable (docker pull ghcr.io/berriai/litellm:litellm-stable_release_v1.83.7-stable); drittens Restart und Verifikation. Für Setups, die kurzfristig nicht updaten können, ist die robusteste Übergangsmaßnahme das Blocken von /prompts/test am vorgelagerten Reverse-Proxy oder Ingress — ein nginx-Snippet location /prompts/test { return 403; } setzt die Lücke für den vom Reverse-Proxy bedienten Verkehr außer Kraft.
Rotieren Sie alle Backend-API-Keys, die in der LiteLLM-Konfiguration hinterlegt sind, sofern die Installation in einem Zeitraum stand, in dem ein Angreifer möglicherweise Zugriff hatte. Das ist die unangenehme, aber strukturell saubere Variante. „Wir wissen nicht, ob wir kompromittiert wurden“ ist nach einer SSTI-Lücke in einem Proxy-Prozess die teurere Antwort.
Detection und Prüfung
Reverse-Proxy-Logs nach SSTI-Mustern durchsuchen. Eine Zeile reicht: grep „POST /prompts/test“ /var/log/nginx/access.log | grep -E '(__class__|__mro__|__subclasses__|__globals__|__builtins__)'. Falco-Regel auf dem Container-Host, die ungewöhnliche Subprozesse aus dem LiteLLM-Prozess erkennt (Spawn von sh, bash, python-Subprozessen mit untypischen Argumenten). Alternative Tetragon-TracingPolicy, die wake_up_new_task-Events von der LiteLLM-Binary an einen externen Sink schickt. Wer auch nur eine verdächtige Anfrage findet: Voll-Container-Forensik (Memory-Dump, Filesystem-Snapshot), Rotation aller hinterlegten Backend-API-Keys, Rebuild des Proxys aus bekanntem Image-Tag.
Betreiberempfehlung
Die operative Entscheidung hängt davon ab, in welchem Setup LiteLLM bei Ihnen läuft. Sofort patchen, wenn Sie LiteLLM in einem Mehrmandanten-Setup betreiben oder als MCP-Backend für Agent-Frameworks einsetzen. Update im 48-Stunden-Wartungsfenster akzeptabel, wenn LiteLLM in einer Single-Tenant-Konfiguration mit eindeutig vertrauenswürdigen API-Key-Inhabern läuft. Sofort blocken statt patchen, wenn ein produktives Wartungsfenster diese Woche nicht möglich ist — den /prompts/test-Endpunkt am Reverse-Proxy auf 403 setzen, das Update in der nächsten regulären Wartung nachziehen.
Mittelständische DACH-KMU mit LiteLLM als zentralem AI-Gateway haben in der Regel eine einzelne Container-Instanz und eine überschaubare Liste von Backend-Anbietern. Hier ist der saubere Weg: Container-Image-Tag auf 1.83.7-stable hochziehen, Backend-API-Keys rotieren, Reverse-Proxy-Logs der letzten 14 Tage auf SSTI-Pattern durchsuchen — 90 Minuten plus Reaktion auf eventuelle Logfunde. Größere Setups mit zentralem AI-Gateway-Team brauchen die zweistufige Variante: erst in der Staging-Region patchen und Smoke-Test der Routing-Tabelle, dann produktive Regionen rolling-update, Backend-Key-Rotation pro Region als separate Stage. LiteLLM in Kubernetes profitiert vom Standard-Rolling-Update-Mechanismus, ergänzt um eine NetworkPolicy, die /prompts/test nur aus dem dedizierten Prompt-Engineering-Namespace erreichbar macht.
Was ich konkret getan habe
Ich betreibe LiteLLM in zwei produktiven Mandantenkonstellationen. Am 7. Mai um 14:30, etwa zwei Stunden nach BSI-Warnung, habe ich in beiden Setups das Container-Image auf 1.83.7-stable hochgezogen, mit kurzem Wartungsfenster und Health-Check-basiertem Rollover. In der einen Mandanten-Konstellation, die seit März auf einer 1.81.x-Version stand, habe ich parallel die Backend-API-Keys rotiert — nicht weil ich Anzeichen einer Kompromittierung gesehen hätte, sondern weil der Zeitraum, in dem die Lücke unwissentlich offen war, nicht durch Logging vollständig abgedeckt war. Detection-seitig habe ich die Falco-Regel auf den Container-Hosts geschärft und einen Reverse-Proxy-Filter eingezogen, der /prompts/test-Aufrufe von außerhalb des explizit benannten Prompt-Engineering-Netzes weiterhin auf 403 blockiert.
Technischer Deep Dive
Die Korrektur in 1.83.7 ist instruktiv. Der relevante Patch ändert den Render-Pfad in /prompts/test von Environment zu SandboxedEnvironment und schaltet zusätzlich eine Allowlist von erlaubten Filtern und globalen Funktionen, die im Sandbox-Render verfügbar sein sollen. Die SandboxedEnvironment blockiert Attribut-Zugriffe auf Methoden, die mit _ beginnen, sowie Calls auf eine Liste bekannter unsicherer Methoden. Das schließt __class__.__mro__ und ähnliche Pfade strukturell. Es ist nicht perfekt — Jinja2-Sandboxen haben in der Vergangenheit eigene Bypass-Lücken gehabt —, aber es ist die richtige Verteidigungs-Schicht für diesen Endpunkt.
Die strategisch interessantere Frage hinter der Lücke ist: warum war der Endpunkt überhaupt unsandboxed, und warum hat Code-Review das nicht gefangen? Die ehrlichste Antwort ist, dass /prompts/test ein „internes Tooling“-Pfad war, der ursprünglich nur als CLI-Hilfe gedacht war und erst später per HTTP-Endpunkt freigeschaltet wurde — ohne dass die Sandbox-Anforderung im Übergang sichtbar mitgeführt wurde. Für die eigene Codebase lohnt sich die Frage: welche Render-Pfade in unserem System nehmen User-Input an, und welche davon laufen in einem expliziten Sandbox-Environment?
Fazit
CVE-2026-42203 ist allein betrachtet eine bekannte SSTI-Pattern-Eskalation in einem populären Open-Source-Projekt, mit klarem Patch und überschaubarer operativer Antwort. In Kombination mit CVE-2026-42208 vom 23. April ist die Linie unangenehmer: die LiteLLM-Proxy-Schicht hat in den letzten 14 Tagen zwei strukturell unterschiedliche Lücken gezeigt, die beide an Stellen sitzen, an denen die meisten Operatoren historisch wenig Aufmerksamkeit investiert haben.
Die Frage lautet nicht, ob LiteLLM ein vertrauenswürdiges Werkzeug ist — das bleibt es nach meiner Einschätzung. Sie lautet, ob die /prompts/*- und Key-Management-Pfade in Ihrer eigenen Installation die gleiche Aufmerksamkeit bekommen wie der /chat/completions-Pfad, der den Proxy für Ihre Anwendung wertvoll macht. Diese Woche ist die Antwort: noch nicht, aber bis Freitag schon.
Persönlicher Hintergrund und technische Details zur Härtung von LiteLLM-Installationen und MCP-Backends: ole-hartwig.eu.