Authgear: Anonymes Auslesen der Projektkonfiguration über Path Traversal

Eine anonyme Anfrage an den Static-Asset-Endpunkt liest über einen Traversal-Pfad die vollständige Projektkonfiguration samt OAuth-Clients und die Hook-Quelltexte des Mandanten.

Advisory-ID: TP-2026-121
Produkt: Authgear (quelloffene Plattform für Authentifizierung und Single Sign-On)
Schwachstellentyp: Path Traversal (CWE-22)
CVE: beantragt (GitHub CNA), Vergabe ausstehend
CVSS 3.1: 7.5 (Hoch) · CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Betroffene Versionen: < 2026-10-08.0
Hersteller-Advisory: GHSA-c7wp-6c82-59rm
Behoben in: 2026-10-08.0
Gemeldet: 7. Oktober 2026

Zusammenfassung

Authgear ist eine quelloffene Plattform für Authentifizierung und Single Sign-On, deren AuthUI statische Assets unter /static/ ausliefert. Das zugehörige Dateisystem löst Pfade gegen die gesamte Ressourcen-Registry der Anwendung auf statt nur gegen das Asset-Verzeichnis, und ein ..-Segment im Pfad führt aus dem Asset-Verzeichnis heraus. Die Integritätsprüfung, die unbekannte Dateinamen abweisen sollte, ist invertiert und wird mit einem beliebigen 8-Zeichen-Hash im Dateinamen übersprungen. Eine einzige anonyme GET-Anfrage liest so die vollständige Projektkonfiguration authgear.yaml mit OAuth-Clients und Identity-Provider-Konfiguration sowie vom Mandanten verfasste Hook-Quelltexte.

Ursache

pkg/util/httputil/file_server.go:193 normalisiert den Anfragepfad, und der Präfixtest gegen das Asset-Verzeichnis in pkg/util/httputil/file_server.go:219 schlägt für einen Traversal-Pfad fehl, sodass die Anfrage in den Fallback-Zweig serveOther (pkg/util/httputil/file_server.go:128) fällt. Dieser Zweig öffnet den Pfad über Open in pkg/auth/handler/webapp/app_static_assets.go:60, das den Namen in :66 zerlegt und in :72 Resources.Resolve gegen die vollständige Descriptor-Registry aufruft, die kein statisches Teilverzeichnis kennt. Der md5-Vergleich in pkg/auth/handler/webapp/app_static_assets.go:89-95 läuft nur innerhalb von if !web.LookLikeAHash(hashInPath), und pkg/lib/web/static_asset_resolver.go:128-130 definiert dieses Prädikat als len(s) == 8, sodass jede 8-Zeichen-Zeichenkette die Prüfung umgeht. Die Route-Kette in pkg/auth/routes.go:81-85 enthält nur Project-Root, CORS und Public-Origin, aber keine Session- oder Authentifizierungs-Middleware. Nur authgear.secrets.yaml bleibt geschützt, weil die Effective-File-Sicht des Secret-Descriptors ErrEffectiveSecretConfig liefert (pkg/lib/config/configsource/resources.go:486).

Proof of Concept

GET /static/..%2fauthgear.deadbeef.yaml        (anonym)
-> 200, vollständige authgear.yaml (id, http.public_origin, oauth.clients, redirect_uris, ...)

GET /static/..%2fdeno%2f<hook>.deadbeef.ts     -> 200, Hook-Quelltext unverändert
GET /static/..%2fauthgear.<32 Zeichen>.yaml    -> 404
GET /static/..%2fauthgear.secrets.deadbeef.yaml -> 500

deadbeef hat genau 8 Zeichen und gilt deshalb als Hash, wodurch der Inhaltsvergleich entfällt. Die Antwort ist byte-identisch mit der Datei auf dem Datenträger des Servers.

Auswirkung

  • Vollständige OAuth-Client-Registry und Identity-Provider-Konfiguration der Installation ohne Konto lesbar.
  • Quelltext jeder vom Mandanten verfassten Ressource, etwa Deno-Hooks, öffentlich abrufbar.
  • Client-IDs und Redirect-URIs liefern die genauen Parameter für Folgeangriffe auf das SSO der Installation.
  • Eine anonyme GET-Anfrage, keine Benutzerinteraktion, Standardkonfiguration.

Referenzen

Steckt so etwas in Ihrer Software?

Diese Schwachstelle hat unser Team im Rahmen seiner Arbeit gefunden. Lassen Sie Ihre Anwendungen von denselben Spezialisten prüfen, mit einem Penetrationstest von turingpoint.