Loopback ist keine Vertrauensgrenze: CVE-2026-2611
Am 19. Mai 2026 veröffentlichte die National Vulnerability Database CVE-2026-2611. In der Assistant-Funktion von MLflow 3.9.0 war die Herkunftsprüfung für die lokalen /ajax-api-Endpunkte fehlerhaft. Eine bösartige Webseite in einem beliebigen Browser-Tab konnte Cross-Origin-Anfragen an den lokalen Server des Assistants senden, dessen Konfiguration auf Vollzugriff umstellen und anschließend über die mitgelieferte Claude-Code-CLI-Integration beliebige Befehle ausführen. Huntr bewertete die Schwachstelle nach CVSS 3.0 mit 9,6 (CRITICAL) und dem Vektor AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H: über das Netzwerk erreichbar, geringe Komplexität, keine Rechte erforderlich, geänderter Wirkungsbereich sowie vollständige Auswirkungen auf Vertraulichkeit, Integrität und Verfügbarkeit.1
Die Ursache ist nicht neu und die Behebung nicht exotisch, aber das Bedrohungsmodell ist neu. Jeder lokale Dienst, der an Loopback bindet und einem Browser-Tab verändernde Endpunkte anbietet, liegt auf einer Vertrauensgrenze. Sobald dieser Dienst einen KI-Agenten steuert, der Dateien lesen, Shell-Befehle ausführen und Code pushen kann, taugt „nur Loopback“ nicht mehr als Sicherheitskontrolle. CVE-2026-2611 ist der Musterfall für eine ganze Schwachstellenklasse, die wiederholt auftauchen wird, je mehr Entwicklertools LLM-Agenten in lokale Web-UIs einbetten.
Kurzfassung
CVE-2026-2611 beschreibt einen unvollständigen CORS-Aufzählungsfehler in MLflow 3.9.0. Die Assistant-Funktion stellte /ajax-api/-Endpunkte bereit, die von MLflows Prüfung is_api_endpoint() nicht erfasst wurden; deshalb übersprang die CORS-blockierende Middleware diese Pfade. Zusätzlich erlaubte die alte CORSMiddleware allow_origins=["*"], sodass eine Cross-Origin-Anfrage von evil.com /ajax-api/3.0/mlflow/assistant/config aufrufen, den Assistant in den Vollzugriffsmodus versetzen und anschließend Shell-Befehle über die mitgelieferte Claude-Code-CLI-Integration senden konnte.1 Die Upstream-Behebung (PR #20832, „Block CORS for ajax paths“) in MLflow 3.10.0 nimmt /ajax-api/ in die geschützte Pfadauflistung auf und beschränkt allow_origins auf die konfigurierte Zulassungsliste plus einen Localhost-Regulärausdruck.2 Die folgenden Abwehrmaßnahmen gelten für lokale KI-Agenten als Klasse, nicht nur für MLflow.
Wichtigste Erkenntnisse
| Rolle | Maßnahme |
|---|---|
| KI/ML-Ingenieure, die MLflow betreiben | Aktualisieren Sie auf MLflow 3.10.0; prüfen Sie jede andere lokale KI-Agenten-UI, die auf Loopback lauscht |
| Sicherheitsteams | Nehmen Sie „lokaler Loopback-Dienst für LLM-Agenten“ in Ihre Bedrohungsmodell-Vorlagen auf; eine CORS-Lücke entspricht in dieser Klasse RCE |
| Tool-Autoren, die lokale Agenten-UIs bauen | Zählen Sie jeden API-Pfadpräfix einmal zentral auf; verbieten Sie allow_origins=["*"] auch bei Servern, die nur an localhost gebunden sind; schützen Sie destruktive Endpunkte mit einer frischen Benutzeraktion, nicht nur mit der Herkunft |
| Engineering-Leads | Isolieren Sie die KI-Coding-Agenten Ihres Teams in Sandboxes und behandeln Sie deren Befehlsfähigkeit als tatsächlichen Schadensradius |
Wie die Angriffskette aussieht
Die fünf Schritte sind kurz. Jeder einzelne nutzt autorisierte Fähigkeiten; die Kombination ist das Problem.
| Schritt | Aktion | Was der Angreifer kontrolliert |
|---|---|---|
| 1 | Benutzer führt lokal mlflow ui aus; der Assistant lauscht auf Loopback (Standard: 127.0.0.1) |
Noch nichts (lokaler Dienst) |
| 2 | Benutzer öffnet evil.com in einem beliebigen Tab, während MLflow läuft |
Den Seiteninhalt |
| 3 | evil.com sendet fetch('http://127.0.0.1:5000/ajax-api/3.0/mlflow/assistant/config', { method: 'PUT', credentials: 'include', body: ... }) |
Die Cross-Origin-Anfrage |
| 4 | MLflow akzeptiert die Anfrage, weil /ajax-api/ nicht in der CORS-blockierenden Pfadauflistung stand; die Assistant-Konfiguration wechselt auf Vollzugriff |
Die Ausführungskonfiguration des Assistants |
| 5 | evil.com sendet Befehlsdaten über den Chat-Endpunkt des Assistants; MLflow ruft die lokale Claude-Code-CLI mit umgangenen Berechtigungsprüfungen auf; Befehle laufen als der Benutzer |
Beliebige Codeausführung |
Der Angreifer muss auf dem Rechner des Opfers nichts installieren. Es reicht, dass das Opfer einen einzigen Tab mit den Angriffsdaten lädt, während mlflow ui läuft. Der Angriff funktioniert von jeder Herkunft aus, weil die alte CORSMiddleware allow_origins=["*"] gesetzt hatte und die pfadbasierte CORS-Blockierung den Präfix /ajax-api/ nicht abdeckte.2
Die Claude-Code-Integration verstärkt die Rechte. MLflows ClaudeCodeProvider findet die lokale claude-CLI über shutil.which("claude") und weist Benutzer bei fehlender Installation auf npm install -g @anthropic-ai/claude-code hin. Wenn das Konfigurationsflag permissions.full_access des Assistants aktiv ist, erweitert der Provider den CLI-Aufruf um --permission-mode bypassPermissions, den Claude-Code-Modus, der interaktive Berechtigungsabfragen unterdrückt und Tool-Aufrufe ohne Benutzerbestätigung ausführen lässt.3 Die autorisierten Fähigkeiten des Agenten (Shell, Dateischreibzugriff, HTTP) werden damit zu einer Remote-Shell mit natürlichsprachlicher UX, also genau zu dem, was ein Angreifer will.
Die Ursache ist eine unvollständige Pfadauflistung
Beim Lesen des Fix-Commits wird der Fehler offensichtlich. MLflows security_utils.py enthielt diese Konstante:
API_PATH_PREFIX = "/api/"
und diese Prüfung:
def is_api_endpoint(path: str) -> bool:
return path.startswith(API_PATH_PREFIX) and path not in TEST_ENDPOINTS
Die CORS-blockierende Middleware rief is_api_endpoint() auf, um zu entscheiden, ob eine Herkunftsprüfung angewendet wird. Jeder Pfad, der nicht mit /api/ begann, lief als Nicht-API-Pfad durch. Der Assistant führte /ajax-api/ für seine browserseitigen Endpunkte ein. Niemand aktualisierte is_api_endpoint(), um den neuen Präfix aufzunehmen.
Die Behebung ist eine einzeilige Verhaltensänderung in security_utils.py:2
API_PATH_PREFIX = "/api/"
AJAX_API_PATH_PREFIX = "/ajax-api/"
def is_api_endpoint(path: str) -> bool:
return (
path.startswith(API_PATH_PREFIX) or path.startswith(AJAX_API_PATH_PREFIX)
) and path not in TEST_ENDPOINTS
Dazu kommt eine parallele Behebung in fastapi_security.py, die allow_origins=["*"] in der alten CORSMiddleware durch die konfigurierte Zulassungsliste plus einen Localhost-Regulärausdruck ersetzt. Zusammengenommen sind das 5 hinzugefügte und 2 entfernte Zeilen in security_utils.py sowie 5 hinzugefügte und 1 entfernte Zeile in fastapi_security.py.2
Das ist die gesamte Schwachstelle. CVE-2026-2611 entstand, weil ein neuer Endpunktpräfix ausgeliefert wurde, ohne die einzige Funktion zu aktualisieren, die aufzählt, welche Pfade CORS-Schutz erhalten. Die Angriffsfläche war eine vergessene Konfigurationskonstante.
Warum sich dieses Muster wiederholen wird
Der Fehler ist älter als MLflow und älter als KI-Agenten. Web-Frameworks liefern Pfadauflistungsfehler aus, seit es Pfadauflistungen gibt. Geändert hat sich die Konsequenz. Eine lokale Web-UI, die einen Endpunkt zu erfassen vergisst, verlor früher vielleicht Konfigurationsdaten oder löste einen Denial of Service aus. Eine lokale Web-UI, die einen Endpunkt vergisst, während ein KI-Coding-Agent mit Shell-Zugriff läuft, verliert die gesamte Entwicklermaschine.
Lokale KI-Agenten-UIs sind eine wachsende Kategorie. Jedes Tool, das einen LLM-Agenten in eine Browser-UI einbettet, die von 127.0.0.1 ausgeliefert wird, gehört dazu: Experiment-Tracker mit Chat-Panels (die MLflow-Form), IDE-Plugins, die einen Agenten über eine Localhost-API steuern, Entwicklungsserver, mit denen eine Erweiterung über HTTP kommuniziert, Web-Dashboards für lokale Modell-Runner. Alle binden an Loopback. Alle stellen verändernde Endpunkte für einen Browser-Tab bereit. Alle führen einen Agenten aus, der Shell-Befehle starten, Dateien schreiben und nach git pushen darf. Jeder davon ist genau einen Pfadauflistungsfehler von CVE-2026-2611 entfernt.
Die gemeinsame Annahme unter dieser Klasse lautet: „Die Same-Origin-Policy des Browsers schützt den Loopback-Server, weil legitime Anfragen ebenfalls von 127.0.0.1 kommen.“ Diese Annahme bricht zusammen, sobald irgendeine Cross-Origin-Schwelle (CORS, Host-Header-Prüfung, Origin-Header-Prüfung, Fetch-Metadata-Header) einen Endpunktpräfix übersieht. Der Browser schützt den Server nicht, wenn der Server die Anfrage ausdrücklich akzeptiert.
Der stille Egress-Angriff, den ich im März beschrieben habe, ist dieselbe gebrochene Vertrauensannahme in die andere Richtung. Stiller Egress versteckt den Ausgang über die autorisierten Tools des Agenten. Loopback-Fehlklassifizierung versteckt den Eingang über die autorisierten Netzwerkaufrufe des Browsers. Beides läuft auf dasselbe hinaus: Die autorisierten Fähigkeiten eines LLM-Agenten werden zum Angriffswerkzeug, sobald eine einzige Grenzprüfung versagt.
Wie die Klasse tatsächlich aussieht
Die Schwachstellenklasse hat vier Zutaten. Ein Dienst ist ausnutzbar, wenn alle vier zutreffen:
- Lokaler Webserver, der an Loopback oder
0.0.0.0gebunden ist. Nur Loopback ist die häufigere Variante. Nicht die Netzwerkbindung schützt einen localhost-gebundenen Dienst vor einem Cross-Origin-Tab, sondern die CORS-, Host- und Origin-Prüfungen des Browsers beziehungsweise Servers. - Verändernde Endpunkte, die ohne Benutzeraktion erreichbar sind. Konfigurationsänderungen, Befehlseinreichungen, Dateischreibvorgänge. Wenn ein
fetch()von beliebiger Herkunft Zustand verändern kann, ist der Dienst erreichbar. - Fähigkeiten, die der lokale Benutzer besitzt, eine Webseite aber nicht besitzen sollte. Lesen des Home-Verzeichnisses, Ausführen von Shell-Befehlen, Aufrufen von Cloud-APIs mit gespeicherten Zugangsdaten, Ändern von Quelldateien.
- Eine fehlende Grenzprüfung. Vergessener Pfadpräfix, Wildcard-
allow_origins, fehlende Host-Header-Prüfung, fehlende Origin-Prüfung, fehlende Durchsetzung von Sec-Fetch-Site.
CVE-2026-2611 erfüllte alle vier Punkte. Die Behebung schließt Punkt vier für den Präfix /ajax-api/ in MLflow. Punkt eins bis drei gelten weiterhin für jedes andere lokale KI-Agenten-Tool. Die nächste CVE in dieser Klasse wird mit anderem Paketnamen identisch aussehen.
Abwehr gegen die lokale Loopback-Klasse von KI-Agenten
Der übliche CORS-Rat (allow_origins auf eine konkrete Liste setzen, Credentials nur bei Bedarf aktivieren) ist notwendig, reicht aber nicht. Diese Klasse braucht tiefere Kontrollen.
Zählen Sie Pfadpräfixe an einer einzigen Stelle auf, und schreiben Sie einen Test, der fehlschlägt, sobald ein neuer Präfix ungeschützt erscheint. MLflows Fehler entstand, weil das Team is_api_endpoint() beim Ausliefern von /api/ aktualisierte und es bei /ajax-api/ vergaß. Ein Test, der jede registrierte Route der FastAPI-App durchläuft, is_api_endpoint() fragt, ob die Route geschützt ist, und bei jedem unbekannten Pfadpräfix fehlschlägt, hätte den Fehler im PR entdeckt. Die Prüfung kostet etwa 20 Zeilen Testcode.
Validieren Sie Origin- und Host-Header, nicht nur CORS. CORS schützt Browser vor der Antwort des Servers. Es schützt den Server nicht davor, die Anfrage anzunehmen. Lokale KI-Agenten-Dienste sollten Anfragen ablehnen, deren Origin-Header nicht in der expliziten Zulassungsliste steht und deren Host-Header nicht 127.0.0.1 oder localhost ist (Letzteres verhindert DNS-Rebinding-Angriffe). Beide Prüfungen sollten standardmäßig geschlossen fehlschlagen.
Schützen Sie destruktive Endpunkte mit Sec-Fetch-Site: same-origin. Browser senden bei jedem Cross-Origin-fetch() Sec-Fetch-Site: cross-site, auch von evil.com nach 127.0.0.1. Die Spezifikation Fetch Metadata Request Headers definiert die Header-Werte, und Chrome, Firefox, Safari sowie Edge senden sie alle.4 Eine Middleware, die Anfragen an verändernde Endpunkte ablehnt, sofern nicht Sec-Fetch-Site: same-origin gesetzt ist, liefert eine zusätzliche Schicht, die nicht davon abhängt, jeden Pfadpräfix im Kopf zu behalten.
Isolieren Sie die Ausführungsfähigkeit des KI-Agenten. Claude Code, Cursor, Aider und Continue laufen standardmäßig mit den vollen Rechten des Benutzers, weil das die einfachste UX ist. Eine Fähigkeits-Sandbox pro Workspace (bwrap mit expliziten Mount-Regeln unter Linux; macOS App Sandbox für Tools, die als .app-Bundles ausgeliefert werden; ein Container pro Workspace für plattformübergreifende Nutzung) reduziert den Schadensradius, ohne den Hauptarbeitsablauf aufzugeben. Die Minderung erzeugt Reibung. Genau das ist der Zweck.
Behandeln Sie Commits des Agenten bis zur Prüfung als nicht vertrauenswürdig. Branch Protection, verpflichtende Reviews, signierte Commits. Das Modell „KI-Agent mit Commit-Zugriff“ bricht in dem Moment zusammen, in dem ein Angreifer die lokale Umgebung des Agenten kompromittiert. Widerspruch im Review (behandelt in AI-Code-Review braucht Widerspruch) gilt auch hier. Wenn KI-Agent und menschlicher Reviewer immer einer Meinung sind, ist der menschliche Reviewer Dekoration.
Wie die nächste CVE dieser Klasse vermutlich aussieht
Die interessante Frage ist nicht, ob die nächste Schwachstelle im Stil von CVE-2026-2611 auftaucht. Interessant ist, welches Paket sie zuerst ausliefert. Kandidaten gibt es im gesamten Ökosystem lokaler KI-Tools: Experiment-Tracker, die einen Agenten in ihre UI einbauen, IDE-Plugins, die über HTTP mit einem lokalen Agenten-Backend sprechen, Entwicklungsserver, die ein Tool während einer Sitzung öffnet, Localhost-APIs, über die Erweiterungen Agenten-UIs steuern. Noch hat keines davon eine CVE in genau dieser Form veröffentlicht. Mehrere enthalten jedoch Codepfade, die an Loopback binden und Cross-Origin-Anfragen akzeptieren, wobei der Browser als Vertrauensschwelle dient.
Die Klasse ist größer als CVE-2026-2611, und das Bedrohungsmodell hat sich verschoben. Eine Entwicklermaschine im Jahr 2026 beherbergt einen KI-Agenten, der Shell-Befehle ausführen, Dateien schreiben, Commits pushen und Cloud-APIs aufrufen kann. Die lokalen Web-UIs, die diese Agenten steuern, erben die Rechte des Agenten über genau die Vertrauensgrenze, die der HTTP-Server der UI durchsetzt. Eine CORS-Fehlkonfiguration in einem Web-Framework von 2020 verlor vielleicht einige Konfigurationsdaten. Eine CORS-Fehlkonfiguration in einer lokalen KI-Agenten-UI von 2026 verliert die gesamte Entwicklermaschine plus Produktions-Deployment-Fähigkeit.
Die Lösung ist kein einzelner Patch. Die Lösung ist eine Klasse von Kontrollen: explizite Pfadauflistung mit Tests, mehrschichtige Header-Validierung, Fähigkeits-Sandboxing und Review-Disziplin bei Agenten-Commits. Tools, die eines davon ohne die anderen ausliefern, liefern den Nachfolger von CVE-2026-2611 mit anderem Präfix aus.
FAQ
Was ist CVE-2026-2611?
CVE-2026-2611 ist die Kennung der National Vulnerability Database für eine fehlerhafte Herkunftsprüfung in der Assistant-Funktion von MLflow 3.9.0. Durch die Schwachstelle kann jede Webseite Cross-Origin-Anfragen an den lokalen /ajax-api-Endpunkt des Assistants senden, dessen Konfiguration auf Vollzugriff umstellen und anschließend über die mitgelieferte Claude-Code-CLI-Integration beliebige Befehle ausführen. CVSS-3.0-Basiswert: 9,6 (CRITICAL). Behoben in MLflow 3.10.0 über PR #20832, „Block CORS for ajax paths“.12
Was war die Ursache?
MLflows Prüfung is_api_endpoint() zählte nur den Pfadpräfix /api/ auf. Als die Assistant-Funktion /ajax-api/-Endpunkte einführte, wurde die Auflistung nicht aktualisiert. Die CORS-blockierende Middleware ließ Cross-Origin-Anfragen an /ajax-api/ dadurch ohne Herkunftsprüfung passieren. Eine zweite Schwäche verschärfte den Fehler: Die alte CORSMiddleware erlaubte allow_origins=["*"], sodass selbst nicht blockierte Pfade freizügige CORS-Header an jede Herkunft zurückgaben. Die Behebung ergänzt AJAX_API_PATH_PREFIX = "/ajax-api/" in der Pfadprüfung und ersetzt allow_origins=["*"] durch die konfigurierte Zulassungsliste plus einen Localhost-Regulärausdruck.2
Wie erkenne ich, ob meine MLflow-Installation betroffen ist?
Führen Sie pip show mlflow | grep Version aus. Laut NVD-CPE-Bereich sind MLflow-Versionen >=3.9.0,<3.10.0 betroffen. MLflow 3.10.0 (veröffentlicht am 20. Februar 2026) enthält die Behebung. Aktualisieren Sie mit pip install --upgrade mlflow und starten Sie laufende mlflow ui-Prozesse neu.
Funktioniert der Angriff auch ohne installierte Claude-Code-CLI?
Der Schritt zur Konfigurationsänderung funktioniert unabhängig davon. Für die beliebige Codeausführung muss die Claude-Code-CLI auf dem PATH des Opfers vorhanden sein, weil MLflows Assistant sie über shutil.which("claude") aufruft. Ohne die CLI wird aus dem Worst Case eher Informationspreisgabe und beliebige Konfigurationsmanipulation statt RCE. Für Benutzer, die das Claude-Code-Backend konfiguriert haben (der dokumentierte Assistant-Setup-Pfad), ist die praktische Gefährdung RCE.
Wie schütze ich andere lokale KI-Agenten-Dienste?
Prüfen Sie auf die vier Zutaten: Loopback- oder Wildcard-Bindung, verändernde Endpunkte, Agentenfähigkeiten und eine einzelne Grenzprüfung, die Lücken haben kann. Ergänzen Sie explizite Origin-Zulassungslisten, Host-Header-Validierung gegen 127.0.0.1/localhost (gegen DNS-Rebinding) und Sec-Fetch-Site: same-origin-Schwellen für destruktive Endpunkte. Isolieren Sie die Ausführungsfähigkeit des Agenten mit bwrap, App Sandbox oder einem Container pro Workspace. Behandeln Sie Git-Commits des Agenten bis zur Prüfung als nicht vertrauenswürdig.
-
National Vulnerability Database. „CVE-2026-2611: MLflow Assistant improper origin validation.“ Veröffentlicht am 19. Mai 2026. CVSS-3.0-Basiswert 9,6 (CRITICAL), Vektor
CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H, ausgestellt von Huntr. Behebung in MLflow 3.10.0 ausgeliefert. https://nvd.nist.gov/vuln/detail/CVE-2026-2611. Ursprünglicher Bericht: https://huntr.com/bounties/8462addd-b464-4a84-b6a2-5529604e6e5a. ↩↩↩ -
MLflow. „Block CORS for ajax paths (#20832).“ Am 16. Februar 2026 von Tomu Hirata gemergt. Geänderte Dateien:
mlflow/server/fastapi_security.py(+5/-1),mlflow/server/security_utils.py(+5/-2), plus Testaktualisierungen. Der Diff ersetzt die Ein-Präfix-Prüfung vonis_api_endpoint()durch eine Zwei-Präfix-Prüfung und beschränktallow_originsder altenCORSMiddlewarevon["*"]auf die konfigurierte Zulassungsliste plus einen Localhost-Regulärausdruck. https://github.com/mlflow/mlflow/commit/8f9c8a53af90842944101eb8b7d60706822c81bc. ↩↩↩↩↩↩ -
MLflow-3.10.0-Quelle.
mlflow/assistant/providers/claude_code.py:shutil.which("claude")-Lookup (Zeilen 268, 280, 355); Installationshinweis"Install it with: npm install -g @anthropic-ai/claude-code"(Zeile 286); Permission-Mode-Eskalationcmd.extend(["--permission-mode", "bypassPermissions"]), gesteuert durchconfig.permissions.full_access(Zeilen 379–381).mlflow/assistant/config.py: StandardwertPermissionsConfig.full_access: bool = False(Zeile 15).mlflow/server/assistant/api.py: Router-Präfix/ajax-api/3.0/mlflow/assistant(Zeile 63); ReaderGET /config(Zeile 261); MutatorPUT /config(Zeile 276) — der PUT-Endpunkt ist das Ziel des Cross-Origin-Angriffs, umfull_accessumzuschalten. Verifiziert anhand des MLflow-3.10.0-sdist auf PyPI (mlflow-3.10.0.tar.gz). ↩ -
W3C. „Fetch Metadata Request Headers.“ Definiert
Sec-Fetch-Siteund seine Wertecross-site,same-origin,same-site,none. Implementiert von Chrome 76+, Firefox 90+, Safari 16.4+ und Edge 79+. https://www.w3.org/TR/fetch-metadata/ ↩