7 Min. Lesezeit
Hoch
Von

BadHost (CVE-2026-48710): Eine Zeile im Host-Header hängt Auth aus — Starlette, FastAPI und jeder MCP-Server unter 1.0.1 sind die Linie

27. Mai 2026. X41 D-Sec hat am 22. Mai im Rahmen einer OSTIF-finanzierten vLLM-Audit-Runde die BadHost-Schwachstelle (CVE-2026-48710) im Starlette-ASGI-Framework offengelegt. Eine einzige Zeile im HTTP-Host-Header reicht, um path-basierte Auth-Middleware auszuhebeln; request.url.path wird aus dem Host-Header rekonstruiert, das ASGI-Routing dagegen aus dem rohen Pfad — ein klassisches Path-Confusion-Pattern, das in jedem Python-Stack mit FastAPI, vLLM, LiteLLM oder einem Model-Context-Protocol-Server greift. Starlette 1.0.1 vom 21.05. schließt die Lücke; für Moselwal-Kunden mit eigenem MCP-Stack oder FastAPI-Backends gehört der Bump in die nächste Wartungs-Runde.

Aufsicht-Stillleben auf einer matt-dunklen Schieferfläche als Arbeitstisch eines Routing-Auditors. Im Zentrum eine kreisrunde niedrige Sortier-Tablette aus brüniertem Messing mit einem dünnen Mittel-Steg, der die Tablette in zwei Pigeonholes teilt — die linke gestempelt /public/discovery, die rechte gestempelt /admin/settings, beide in monospaced Letterpress. Quer über dem Steg liegt ein einzelner cremefarbener Brief: die obere Hälfte gestempelt Host: example.com/.well-known/ ragt in die /public-Pigeonhole, die untere Hälfte mit dem Slip path: /admin/settings ragt in die /admin-Pigeonhole. Auf der oberen /public-Hälfte sitzt ein einzelner oxblutroter Wachstropfen mit einem brünierten Messing-Petschaft als Auth-Stempel. Links unten ein aufgeschlagenes leinenbespanntes Audit-Hauptbuch mit drei monospaced Bleistift-Einträgen, einer davon lesbar scope["path"], daneben ein cremefarbenes Karteikärtchen mit der monospaced Letterpress-Aufschrift CWE-444. Rechts oben im Negativraum ein brünierter Messing-Stempel mit Walnussgriff und ein zweites Karteikärtchen mit der Letterpress-Aufschrift Starlette 1.0.1. Kühles Studio-Schlüssellicht von oben links, sanftes warmes Rim-Licht von unten rechts; Hintergrund verläuft ins Schiefergrau und Beinahe-Schwarz am rechten Bildrand, für das Title-Overlay frei.
AI-generated · gpt-image 2.0

TL;DR — die 90-Sekunden-Zusammenfassung

Was wurde veröffentlicht?

Eine Authentication-Bypass-Schwachstelle in Starlette < 1.0.1, dem ASGI-Framework, auf dem FastAPI, vLLM, LiteLLM, das offizielle Model-Context-Protocol-Python-SDK und nach OSTIF-Schätzung mehr als 400.000 GitHub-Repositories aufsetzen. CVE-2026-48710, Klasse CWE-444 (Inconsistent Interpretation of HTTP Requests / HTTP Request Smuggling), öffentlich seit 22.05.2026 zusammen mit der Scanner-Domain badhost.org.

Wie schwer?

X41 D-Sec stuft CVSS 7.0 (High) ein, Starlette-Maintainer 6.5 (Moderate). Die Differenz hängt an einer Annahme: der Maintainer sieht Path-based Auth als Anti-Pattern und damit die Klasse als enge, der Auditor sieht Path-based Auth als Default-Pattern in MCP-Servern, FastAPI-Auth-Decorators und Reverse-Proxy-Setups — also als breite Realität. X41 hat in CodeQL-Scans mehrere Stacks identifiziert, in denen der Bypass über sekundäre Effekte zu RCE eskalierbar war.

Welcher technische Hebel?

Starlette baut request.url per String-Konkatenation aus Host-Header und Pfad. Wenn der Host-Header ein /, ? oder # enthält, verschiebt sich die URL-Grenze beim Re-Parse; der ASGI-Server routet weiterhin gegen den rohen Pfad in scope["path"], die Middleware liest aber request.url.path und sieht etwas anderes.

Warum ist MCP besonders exponiert?

Die Model-Context-Protocol-Spezifikation schreibt unauthentifizierte OAuth-Discovery-Endpunkte vor — /.well-known/oauth-authorization-server, /.well-known/oauth-protected-resource, /.well-known/openid-configuration sind per Definition öffentlich. Genau diese Pfade liefern die zuverlässigste Host-Header-Substitution. Ein MCP-Server, der path-prefix-Auth für /tools, /resources oder /prompts macht, ist mit den drei öffentlichen Discovery-Pfaden in der Hand des Angreifers.

Bin ich als Moselwal-Kunde betroffen?

Direkt, wenn Sie einen eigenen MCP-Server (Anthropic-Connector, interne Tools), eine FastAPI-Anwendung, ein vLLM- oder LiteLLM-Deployment oder einen OpenAI-Shim-Proxy laufen haben. Indirekt über transitive Dependencies in nahezu jedem modernen Python-AI-Stack — Starlette ist die Pflicht-Dependency von FastAPI und damit von einer breiten Klasse von Agent-Harness-Komponenten.

Sofort-Mitigation ohne Patch?

Bei Reverse-Proxy-Setup (nginx, Traefik, Caddy, AWS ALB): Host-Header serverseitig auf die erwartete Domain normalisieren und Slashes, Fragezeichen, Hash-Zeichen im Host-Header zurückweisen. In der Auth-Middleware: scope["path"] verwenden statt request.url.path — das ist der Pfad, gegen den der Router tatsächlich entscheidet. Beides löst die Klasse, aber der Pull auf Starlette 1.0.1 ist der kürzere Weg.

 

Was ist passiert

Die Disclosure-Kette ist nüchtern dokumentiert. X41 D-Sec identifizierte BadHost am 27. Januar 2026 im Rahmen einer von OSTIF (Open Source Technology Improvement Fund) finanzierten Audit-Runde des vLLM-Inferenz-Servers. Am 4. Februar ging die koordinierte Meldung an die Starlette-Maintainer mit Proof-of-Concept; Acknowledgment am 5. Februar. Ein Patch-Vorschlag lag am 1. März vor, das eigentliche Release Starlette 1.0.1 erschien aber erst am 21. Mai — knapp drei Monate nach dem Patch-Vorschlag. Am 22. Mai ging die Disclosure öffentlich, parallel mit der Scanner-Domain badhost.org und X41s Detektor-Werkzeug. Die Lage ist seitdem auf einschlägigen Tech-Briefings (CSO Online, InfoWorld, Cyber Kendra, Help Net Security, SC Media) breit dokumentiert; der Hacker-News-Diskussionsfaden hat dreistellige Kommentarzahlen erreicht. Das BSI hat zum Stand heute keine eigene Warnung publiziert.

Technische Einordnung

Strukturell ist BadHost ein Path-Confusion-Vorfall in CWE-444. Starlette rekonstruiert request.url über eine String-Konkatenation f"{scheme}://{host}{path}{query}{fragment}", wobei host direkt aus dem HTTP-Host-Header kommt. Anschließend wird die zusammengebaute URL erneut geparsed; ein / im Host-Header verschiebt dabei die Pfad-Grenze, ein ? die Query-Grenze, ein # die Fragment-Grenze. Das Resultat: request.url.path ist eine andere Zeichenkette als scope["path"]. Der ASGI-Server (uvicorn, hypercorn) routet gegen scope["path"], jede Middleware, die request.url.path auswertet, sieht aber die manipulierte Variante.

In CVSS-Begriffen, und hier liegt die Diskrepanz zwischen Maintainer und Auditor: AV:N (network), AC:L (low complexity), PR:N (no privileges — ein offener Endpunkt wie ein MCP-Discovery-Pfad genügt), UI:N (no user interaction), Scope:Changed oder Unchanged je nach Stack, C:H/I:H/A:L. Der Maintainer geht von Scope:U und niedrigerer Confidentiality aus, weil er Path-based Auth als Anti-Pattern liest; X41 geht von Scope:C aus, weil in den real existierenden FastAPI- und MCP-Codebasen die Auth genau über request.url.path läuft und der Auth-Bypass damit den gesamten geschützten Endpunkt-Bereich öffnet.

Bedeutung für den Mittelstand

Bei unserer Kundschaft sitzt Starlette in drei Klassen von Stacks. Erstens: eigener MCP-Server für interne Tool-Integration in Claude- oder Anthropic-Agent-Workflows. Das ist die Klasse mit der schärfsten Exposure — die OAuth-Discovery-Pfade sind öffentlich, die Tool-Endpunkte sind durch path-prefix-Auth geschützt, und genau diese Architektur ist das BadHost-Lehrbuchbeispiel. Zweitens: FastAPI-Backends in Plattform-Diensten (Form-Eingaben, Webhook-Endpunkte, AI-Funktions-Wrapper, interne Verwaltungs-APIs). Hier ist die Auth-Klasse heterogener, aber path-prefix-Checks sind ein verbreitetes Muster. Drittens: transitive Exposure über vLLM (Inferenz-Server für offene Modelle) und LiteLLM (OpenAI-Shim-Proxy für Multi-Model-Routing); beide nutzen Starlette als HTTP-Schicht, beide sind im Self-Hosted-Sovereign-Hosting-Trend der letzten Monate breit eingesetzt.

Compliance-seitig wirkt der Vorfall auf mehreren Achsen. NIS-2 Art. 21 verlangt Patch-Disziplin entlang der Lieferkette, und Starlette ist Lieferketten-Bestandteil. BSI APP.6 (Allgemeine Software) und APP.4 (Business-Anwendungen) tragen den Befund; eine MCP-Server-Architektur fällt zudem unter BSI APP.4.2 (Datenbanken) oder APP.4.3 (Server-Webanwendungen), je nach Ausprägung. DSGVO Art. 32 trifft jede Pipeline, die personenbezogene Daten über den MCP-Tool-Layer reicht — ein Auth-Bypass auf einem Tool-Endpunkt ist eine Verletzung der Vertraulichkeit. Für DORA-Pflichtige (Finanzdienstleister) wandert der Befund in die IKT-Drittparteienregister-Erfassung, für MaRisk-Häuser in die nächste IKS-Runde. Der EU AI Act Art. 25 (Deployer-Pflichten) ergänzt für KI-Systeme im hochriskanten Anwendungsbereich.

Bedeutung für die technische Entwicklung

Methodisch zeichnet sich eine Spur ab, die wir in der Daily-News-Welle der letzten zwei Wochen wiederholt gesehen haben. OSTIF-finanzierte Audits liefern reproduzierbar substantielle Befunde an offenen Open-Source-Komponenten — das war bei der Mythos-/Glasswing-Audit-Welle auf Symfony und Twig im April und Mai der Fall, und es ist hier in der vLLM-Audit-Runde wieder so. Die Finanzierungs-Schicht ist nicht nebensächlich: ein Open-Source-Maintainer-Team allein hätte die drei Monate zwischen Patch-Vorschlag und Release wahrscheinlich nicht in dieser Qualität überbrücken können, wenn die Disclosure-Kette nicht von einer dedicated Audit-Organisation getragen worden wäre. Die Lehre für den Mittelstand ist nicht „mehr Open Source verwenden“ oder „weniger“, sondern: bei Stack-Komponenten mit hohem Verbreitungsgrad lohnt die Prüfung, ob eine dokumentierte Audit-Quelle existiert.

Architektonisch sitzt die schärfste Lehre in der Auth-Disziplin. Path-based Auth-Middleware ist nicht per se ein Anti-Pattern — sie ist in vielen Architekturen das einzige praktikable Modell, etwa wenn der Reverse-Proxy keinen Zugriff auf die interne Auth-Logik hat oder wenn die Anwendung selbst die Auth-Regeln trägt. Was die Klasse aber verlangt, ist die Prüfung der Quelle: scope["path"] (also der Pfad, den der ASGI-Server tatsächlich routet) ist die einzige verlässliche Zeichenkette für eine Auth-Entscheidung; request.url.path ist das Convenience-Objekt, das jederzeit kippen kann, sobald eine Komponente in der Kette einen Header anders interpretiert. Diese Trennung gilt nicht nur für Starlette; sie ist eine generelle Disziplin für alle HTTP-Frameworks, in denen URL und Pfad aus verschiedenen Quellen rekonstruiert werden.

Konkrete Handlungsempfehlung

In dieser Reihenfolge. Erstens, inventarisieren Sie heute alle Python-ASGI-Stacks mit Starlette als direkter oder transitiver Dependency: eigene MCP-Server, FastAPI-Backends, vLLM-/LiteLLM-Deployments, OpenAI-Shim-Proxies, Agent-Harness-Komponenten. pip show starlette und pipdeptree --reverse starlette liefern den Überblick. Zweitens, ziehen Sie Starlette auf 1.0.1 in einer Test-Pipeline und fahren Sie einen Smoke-Test gegen die Auth-Pfade (interner Curl mit manipuliertem Host-Header, Test gegen die Discovery-Endpunkte). Drittens, bei Architekturen mit path-prefix-Auth: prüfen Sie, ob die Middleware scope["path"] oder request.url.path verwendet, und wechseln Sie im zweiten Fall auf scope["path"]. Viertens, im Reverse-Proxy (nginx, Traefik, Caddy, AWS ALB) Host-Header-Normalisierung aktivieren — Slashes, Fragezeichen und Hash-Zeichen im Host-Header zurückweisen. Wenn diese vier Schritte aus eigener Kraft nicht laufen, sprechen Sie mit uns: Moselwal richtet MCP- und FastAPI-Stacks, in denen die Auth-Disziplin entlang scope["path"] und nicht entlang request.url.path geführt wird.

Dieser Beitrag spiegelt unsere technische und strategische Einschätzung. Er ersetzt keine Rechtsberatung und keine Datenschutz-Folgenabschätzung.

Quellen

Über den Autor

Foto von Kai Ole Hartwig.

Kai Ole Hartwig

Founder · Moselwal Digitalagentur · OnlyOle

Programmiert seit 2002 – autodidaktisch gelernt, 2012 mit KO-Web selbständig gemacht, heute Moselwal. Über 100 Projekte, Fokus auf Security, Performance, Automatisierung und Qualität.