flawopen.com/Teardowns/cve-2026-90970-gitlab-ai-gateway-prompt-template-sandbox-escape
CVE-2026-90970: Prompt-Sandbox-Ausbruch im GitLab AI Gateway
Ein speziell gestalteter Duo-Agent-Platform-Flow konnte aus der Prompt-Template-Sandbox des AI Gateway ausbrechen und Befehle ausführen. Betreiber eines selbst gehosteten Gateways sollten auf die korrigierte Version ihres GitLab-Zweigs aktualisieren.[1], [4]
Stellen Sie sich eine Person vor, die aus Gesprächsprotokollen einen Bericht erstellt. Sie soll freigegebene Felder als einfachen Text übernehmen. Ein präpariertes Template konnte sie jedoch dazu bringen, die Funktion „Wiederherstellen“ des Ablageordners aufzurufen. Dadurch baute die Anwendung aus gespeicherten Daten aktive Objekte, statt nur Wörter zu kopieren. So wurde die Grenze zwischen dem Anzeigen von Daten und ihrer Interpretation durch die Anwendung überschritten. Der Bericht des Forschers beschreibt den konkreten Weg über parse_raw() und pickle; GitLabs Hinweis bestätigt den Sandbox-Ausbruch und die Befehlsausführung, aber nicht alle Einzelschritte.[3], [6]
Kernkonzepte & Begriffe
AI Gateway- GitLab-Dienst, der KI-Funktionen mit Modellanbietern verbindet; das selbst gehostete Gateway-Image hat eine eigene Version.[5], [1]
Prompt template- Vorlage, die feste Anweisungen mit Laufzeitwerten wie Flow-Eingaben und Gesprächskontext verbindet.[3], [6]
Framework-Zuordnungen
- CWE-Referenz für die in diesem Leitfaden beschriebene Schwachstelle: CWE-1336
Ursachenanalyse
GitLab bestätigt, dass ein authentifizierter Benutzer mit Zugriff auf Duo Agent Platform unter bestimmten Bedingungen eine spezielle Flow-Konfiguration nutzen konnte, um die Prompt-Template-Sandbox zu umgehen und beliebige Befehle auf dem AI Gateway auszuführen. Das Problem ist CWE-1336, CVSS 9,9. Der Hinweis nennt nicht alle Bedingungen oder die genaue verwundbare Funktion. Ein öffentlicher Commit vom 17.09.2026 ergänzt PromptSandboxedEnvironment, das Methodenaufrufe auf gebundenen Objekten laut Beschreibung verhindert, und härtet Jinja-Operationen und -Filter. Das passt zur Beschränkung von Template-Aktionen auf Laufzeitobjekten, doch der Commit nennt dieses CVE nicht und öffentliche Quellen verbinden ihn nicht mit den korrigierten Images. Als separate öffentliche Härtungsänderung darstellen; keine öffentliche Quelle verbindet sie mit diesem CVE oder den korrigierten Images. Das öffentliche GitLab-Arbeitselement Nr. 1850 beschreibt einen genaueren Pfad: Ein Jinja-Template ruft parse_raw() auf einem HumanMessage von LangChain aus dem Gesprächsverlauf auf und löst dadurch die Pickle-Deserialisierung aus. Das Arbeitselement ordnet diese Demonstration dem Bericht des Forschers zu und sagt, sie habe in der GitLab-Staging-Umgebung stattgefunden; der Herstellerhinweis nennt nicht alle betroffenen Bedingungen.[1], [3], [4], [2]
Korrigierte Releases des selbst gehosteten AI Gateway
| Bereitstellung / Release-Zweig | Korrigiertes AI-Gateway-Release | Maßnahme |
|---|---|---|
| Selbst gehostetes GitLab, Zweig 19.2 | 19.2.4 | Auf den passenden selbst gehosteten Gateway-Image-Tag aktualisieren und das bereitgestellte Image prüfen. |
| Selbst gehostetes GitLab, Zweig 19.3 | 19.3.2 | Auf den passenden selbst gehosteten Gateway-Image-Tag aktualisieren und das bereitgestellte Image prüfen. |
| Selbst gehostetes GitLab, Zweig 19.4 | 19.4.1 | Auf den passenden selbst gehosteten Gateway-Image-Tag aktualisieren und das bereitgestellte Image prüfen. |
| Von GitLab gehostetes AI Gateway | Laut GitLab bereits behoben. | Prüfen, ob das Deployment das von GitLab gehostete Gateway nutzt; die Hinweise zu selbst gehosteten Images gelten hier nicht. |
Schritt-für-Schritt Angriffsablauf
Die Template-Ausführung überschreitet die Sandbox-Grenze
Das öffentliche GitLab-Arbeitselement Nr. 1850 berichtet, dass ein Template parse_raw() auf einem HumanMessage von LangChain aus dem Gesprächsverlauf aufrufen und dadurch die Pickle-Deserialisierung auslösen konnte. Dies ist der vom Forscher dokumentierte Pfad; leite daraus weder alle betroffenen Flows noch den Herstellerpatch ab.[3]
Quellcode: Verwundbar vs. Sicher
GitLab-Arbeitselement 1850 berichtet, dass der verwundbare Flow ein HumanMessage-Objekt von LangChain an Jinja weitergab, wo ein Template parse_raw() aufrufen und die Pickle-Deserialisierung auslösen konnte. Dieses defensive Beispiel hält Nachrichtenobjekte aus dem Template-Kontext heraus, übergibt nur Text und verweigert den Zugriff auf aufrufbare Attribute und Methoden. Es veranschaulicht die zu schließende Grenze, ist aber nicht der von GitLab veröffentlichte Patch. Der öffentliche Commit 89b72644 ist eine separate Sicherheitsänderung: Sein Titel betrifft Jinja-Block-Set-Schreibvorgänge; keine öffentliche Quelle verbindet ihn mit CVE-2026-90970 oder den korrigierten Images. Betreiber sollten die vom Hersteller genannten behobenen Versionen installieren.[3], [2], [6]
Quelltextauszug: ai_gateway/prompts/base.py (gemeldeter verwundbarer Formatter; illustrative Härtung)
# Auszug aus dem verwundbaren Pfad, beschrieben in GitLab-Arbeitspunkt 1850.
from jinja2 import PackageLoader
from jinja2.sandbox import SandboxedEnvironment
from langchain_core.prompts.string import DEFAULT_FORMATTER_MAPPING
from typing import Any
jinja_loader = PackageLoader("ai_gateway.prompts", "definitions")
jinja_env = SandboxedEnvironment(loader=jinja_loader)
def jinja2_formatter(template: str, /, **kwargs: Any) -> str:
return jinja_env.from_string(template).render(**kwargs)
DEFAULT_FORMATTER_MAPPING["jinja2"] = jinja2_formatter
# Beispiel für ein Schutzmuster; dies ist kein GitLab-Patch für diese CVE.
from typing import Any
from jinja2 import StrictUndefined
from jinja2.sandbox import ImmutableSandboxedEnvironment
class DataOnlyPromptEnvironment(ImmutableSandboxedEnvironment):
def is_safe_attribute(self, obj: Any, attr: str, value: Any) -> bool:
if callable(value):
return False
return super().is_safe_attribute(obj, attr, value)
def is_safe_callable(self, obj: Any) -> bool:
return False
def render_prompt(template: str, history: list[Any]) -> str:
safe_history = []
for message in history:
content = message.content
if not isinstance(content, str):
raise TypeError("prompt history must contain text only")
safe_history.append({"content": content})
env = DataOnlyPromptEnvironment(undefined=StrictUndefined)
return env.from_string(template).render(history=safe_history)
Checkliste für Engineering & Systemsicherheit
- ✓Aktualisieren Sie das selbst gehostete Gateway auf 19.2.4, 19.3.2 oder 19.4.1 des passenden GitLab-Zweigs und verwenden Sie den Image-Tag aus der Installationsdokumentation.[1], [5]
- ✓Klären Sie, ob das Gateway selbst oder von GitLab gehostet wird. GitLab zufolge waren GitLab.com, GitLab Dedicated und Instanzen mit GitLab-Gateway bereits gepatcht.[1]
- ✓Betrachten Sie eine Template-Sandbox nicht als vollständige Isolation, wenn Templates lebende Anwendungsobjekte erhalten.[6]
- ✓Übergeben Sie nur inerte Daten; Methoden, Deserialisierer, Datei-/Prozesshandles und Serviceobjekte gehören nicht in den Template-Kontext.[6], [2]
- ✓Beschränken Sie Attribute und Aufrufe, prüfen Sie Filter auf direkte Methodenaufrufe und testen Sie die produktive Jinja-Version und Konfiguration.[3], [2], [6]
- ✓Ergänzen Sie Tests, die unsichere Objektoperationen zurückweisen und normales String-Rendering erhalten; verwenden Sie keine echten Befehlspayloads.[3], [6]
- ✓Leiten Sie aus dem Hinweis allein weder eine öffentliche Angriffskampagne noch eine vollständige Kette ab. NVD verzeichnet die SSVC-Einschätzung des CISA Coordinator am 02.10.2026 mit „exploitation: none“; das ist ein datierter Stand und keine Aussage über spätere Aktivitäten.[1], [4]
Quellen
- GitLab AI Gateway Critical Patch Release: 19.2.4, 19.3.2, and 19.4.1
- GitLab-Commit 89b72644 — separate Härtung ohne bestätigten CVE-Bezug: „fix(prompts): block Jinja block-set NSRef writes on non-namespace objects“
- GitLab AI Gateway work item 1850 (reporter account; reproduction material omitted)
- NVD: CVE-2026-90970
- GitLab Self-Hosted AI Gateway installation guide
- Jinja 3.1 Sandbox documentation