SvelteKit ist ein beliebtes Full-Stack-JavaScript-Framework, und Vercel ist die am häufigsten genutzte Bereitstellungsplattform dafür. Was wäre, wenn wir Ihnen sagen würden, dass alle Apps, die mit dieser Kombination erstellt wurden, anfällig dafür sind, dass Angreifer Antworten von beliebigen Routen anderer angemeldeter Benutzer lesen können?
Nun, es stimmt. Dieser Angriffsvektor, Cache Deception genannt, ist genau das, was einer der KI-Agenten gefunden und uns gemeldet hat, während wir Aikido Attack testeten. Und obwohl wir anfangs skeptisch waren, haben wir die Schritte nachvollzogen und festgestellt, dass wir die Schwachstelle perfekt reproduzieren konnten. Wir haben Vercel schnell benachrichtigt, und die Schwachstelle wurde nun für alle Benutzer automatisch behoben.
Hinweis: Das Problem kann in Aikidos Intel-Datenbank eingesehen werden und hat die reservierte CVE-Nummer: CVE-2026-27118. Wir haben auch ein separates Problem gefunden, das eine Denial of Service in einer experimentellen Funktion von SvelteKit ermöglicht. Dies wurde ebenfalls offengelegt und behoben.
Kurze Zusammenfassung
Der __pathname Query-Parameter im SvelteKit-Vercel-Adapter kann den Pfad von überall her überschreiben. Auf Vercel hat jede Datei unter /_app/immutable/ unterschiedliche Cache-Control: Header, damit sie zwischengespeichert werden kann. Indem man dies mit einem gefälschten Pfad präfixiert und umschreibt, um sensible Inhalte zu enthalten, wird die Antwort erzwungen zwischengespeichert, was einem Angreifer ermöglicht, sie durch den Besuch derselben URL ohne Cookies abzurufen.
Proof-of-Concept-URL:
https://example.vercel.app/_app/immutable/x?__pathname=/api/session
Erkennung
Wir erzählen diese Geschichte aus der Perspektive des KI-Pentest-Agenten, der die Schwachstelle gefunden hat, beginnend vom initialen Gadget bis zur vollständigen Ausnutzung, und wir werden dabei einige interessante Ideen besprechen. Werden Sie zum Roboter und lassen Sie uns forschen!
Wenn Sie den SvelteKit-Quellcode lesen, stoßen Sie auf einige „Adapter“, die als Middleware zwischen einer Hosting-Plattform wie Vercel und dem Framework SvelteKit fungieren. Dies ermöglicht es, spezielle Regeln auf Anfrage und Antwort anzuwenden, die für die internen Abläufe der Plattform erforderlich sind. Vercel hat dies in serverless.js:
const DATA_SUFFIX = '/__data.json';
fetch(request) {
// If this is an ISR request, the requested pathname is encoded
// as a search parameter, so we need to extract it
const url = new URL(request.url);
let pathname = url.searchParams.get('__pathname');
if (pathname) {
// Optional routes' pathname replacements look like `/foo/$1/bar` which means we could end up with an url like /foo//bar
pathname = pathname.replace(/\/+/g, '/');
url.pathname = pathname + (url.pathname.endsWith(DATA_SUFFIX) ? DATA_SUFFIX : '');
url.searchParams.delete('__pathname');
request = new Request(url, request);
}
return server.respond(request, {
getClientAddress() {
return /** @type {string} */ (request.headers.get('x-forwarded-for'));
}
});
}
Wir können lesen: „Wenn dies eine ISR-Anfrage ist, wird der angeforderte Pfadname als Suchparameter kodiert.“ Der Code nimmt diese pathname-Variable (aus dem ?__pathname= Query-Parameter) und schreibt den url.pathname damit um. Die Anfrage ignoriert die ursprüngliche URL und verwendet stattdessen nur diesen __pathname stattdessen.
Es scheint jedoch keine Prüfungen bezüglich dieser Incremental Static Regeneration (ISR)-Anfragen zu geben. Unterstützen also alle Anfragen diesen Parameter?
Die Antwort ist ja, und genau hier liegt die Schwachstelle! Jeder Pfad kann durch jeden anderen Pfad mit nur einem Query-Parameter überschrieben werden. Ein einfacher Test wie /?__pathname=/404 würde tatsächlich einen 404-Fehler anstelle der Startseite anzeigen.

Das mag sich nur wie eine merkwürdige Funktion anhören. Warum sollte es gefährlich sein? Nun, das ist es nicht, bis Caching ins Spiel kommt.
Cache Poisoning?
Wenn wir jeden Pfad umschreiben können, um auf eine andere Ressource zu zeigen, was passiert, wenn diese manipulierte Ressource gecacht wird? Das war auch unsere erste Idee. Wenn wir den Quellcode einer SvelteKit-App überprüfen, werden wir etwas Ähnliches sehen:
import("./_app/immutable/entry/start.CLO1Dlt2.js"),
import("./_app/immutable/entry/app.kQF6jJr8.js")
Der Pfad /_app/immutable/entry/start.CLO1Dlt2.js gibt JavaScript zur Ausführung zurück, und bei Betrachtung der Antwort Cache-Control: zeigen uns die Header, dass sie tatsächlich gecacht ist. Dies ist für statische Ressourcen zu erwarten:
Age: 618
Cache-Control: public, immutable, max-age=31536000
X-Vercel-Cache: HIT
Wenn wir unser ?__pathname= Parameter nutzen könnten, um die Anfrage umzuschreiben, sodass sie auf einen vom Angreifer kontrollierten Pfad, wie einen Dateiupload, zeigt, und sie immer noch unter demselben einfachen /_app/immutable/entry/start.CLO1Dlt2.js Pfad gecacht würde, den jeder Benutzer lädt, hätten wir XSS bei jedem Benutzer. Sehen wir uns an, was passiert, wenn wir diesen Query-Parameter zu unserer Anfrage hinzufügen:
GET /_app/immutable/start.CLO1Dlt2.js?__pathname=/ HTTP/2
Host: example.vercel.app
In der Antwort erhalten wir gute und schlechte Nachrichten von den Headern:
Age: 935
Cache-Control: public, immutable, max-age=31536000
X-Vercel-Cache: HIT
Der Age: hat sich um die Zeit erhöht, die zum Schreiben des obigen Absatzes benötigt wurde, und der HIT bedeutet, dass mit unserem hinzugefügten Query-Parameter, derselbe Cache-Eintrag getroffen wird wie der, den jeder lädt. Gleichzeitig bedeutet dies jedoch, dass der alte JavaScript-Inhalt zurückgegeben wird und nicht der Inhalt unseres umgeschriebenen Pfades. Wenn das der Fall ist, könnten wir den Cache leeren und dann die Ersten sein, die ihn anfordern, damit unsere Payload stattdessen gecacht werden kann?
Leider nicht. Die Vercel-Plattform ist aufgrund ihrer serverlosen Architektur komplexer und erreicht für eine solche statische Ressource nicht einmal den Adapter-Code. Dies liegt daran, dass statische Assets auf einer höheren Ebene gecacht und zurückgegeben werden, sodass wir sie niemals manipulieren können.
In diesem Fall ist Vercel selbst die einzige anfällige Plattform, sodass wir keine anderen ausnutzbaren Szenarien finden können. Wir sind in einer Sackgasse gelandet.
Cache Deception!
Zum nächsten Problem mit Web-Caching: Cache Deception. Bei dieser weniger bekannten Technik leitet ein Angreifer ein Opfer auf eine sensible Seite um, die es mit seinen Cookies abrufen kann. Wenn der Cache diese Seite speichert, ohne zu berücksichtigen, welcher Benutzer sie angefordert hat, kann der Angreifer später dieselbe URL besuchen und die privaten Daten des Opfers aus dem Cache einsehen. Das Problem ist, dass der Cache Antworten nur basierend auf der URL speichert und dabei ignoriert, dass verschiedene Benutzer mit unterschiedlichen Login-Cookies unterschiedliche Inhalte sehen sollten.
Wenden wir diese Idee auf unser ?__pathname= Gadget an, können wir unsere URL so aussehen lassen, als würde sie auf einen statischen Pfad zeigen, aber tatsächlich auf sensible Inhalte verweist. Die Caching-Schicht kann auf diesen statisch aussehenden Pfad reagieren und explizite Cache-Control: Header hinzufügen und die private Antwort überschreiben.
Während einige Cache-Kriterien dokumentiert sind, zeigte unsere Untersuchung weitere Regeln auf. Eine, mit der wir bereits vertraut sind: Pfade, die mit /_app/immutable/. jegliche 200 OK-Antwort. Um die bereits generierten Assets zu vermeiden, können wir zunächst auf ein gefälschtes Asset verweisen. Dann schreiben wir es auf einen beliebigen sensiblen Pfad um, zum Beispiel /api/session:
https://example.vercel.app/_app/immutable/x?__pathname=/api/session
Und da haben wir unsere finale Payload. Wenn ein eingeloggtes Opfer diesen Link besucht, wird eine Anfrage wie die folgende gesendet:
GET /_app/immutable/x?__pathname=/api/session HTTP/2
Host: example.vercel.app
Cookie: auth=...
SvelteKits Vercel-Adapter schreibt den Pfadnamen um zu /api/session, und wird von der App verarbeitet. Der auth= Cookie wird verifiziert und ihr Session-Token wird zurückgegeben:
HTTP/2 200 OK
Age: 0
Cache-Control: public, immutable, max-age=31536000
...
Server: Vercel
X-Vercel-Cache: MISS
Content-Length: 16
{"token":"1337"}Während der Cache-Control: Header normalerweise lauten würde max-age=0 für diesen Endpunkt, erzwingt die Caching-Schicht von Vercel das Caching aufgrund des /_app/immutable/ Präfixes.
Sobald der Angreifer weiß, dass ein Opfer umgeleitet wurde, kann er dieselbe URL selbst anfordern, ohne Cookies:
GET /_app/immutable/x?__pathname=/api/session HTTP/2
Host: example.vercel.appSie erhalten dieselbe Antwort wie ein HIT jetzt, und kann das Token des Opfers lesen.
HTTP/2 200 OK
Age: 22
Cache-Control: public, immutable, max-age=31536000
...
Server: Vercel
X-Vercel-Cache: HIT
Content-Length: 16
{"token":"1337"}
Durch den Einsatz von Cache Bustern (einzigartigen Dummy-Pfaden) und einer Überprüfung nach der Weiterleitung hätte dies in großem Umfang ausgenutzt werden können. Da diese Schwachstelle lediglich Teil der SvelteKit-Basis ist, würde jede SvelteKit-Website auf Vercel, die Cookies zur Authentifizierung verwendet, das Abrufen beliebiger Antworten ermöglichen.
Die Folgen
Wir haben das Problem schnell an Vercel gemeldet, die einen Fix fanden, um auf jedem /_app/immutable/ Pfad erzwungen 404 zurückzugeben und den __pathname Parameter zu entfernen. Da sie ihre gesamte Plattform kontrollieren, löst dies das Problem automatisch für alle Benutzer, ohne dass ein manueller Patch erforderlich ist.
Eine wichtige Erkenntnis aus dieser Schwachstelle ist, dass Caching immer heikel ist. Einfache Regeln, wie eine Präfixübereinstimmung, können von unerwarteten Plattformfunktionen ausgenutzt werden, die Sie nicht einmal implementiert haben.
Deshalb kann Pentesting so nützlich sein. Probleme wie dieses wären allein durch Code schwer zu entdecken, aber durch eine reale Bereitstellung können versteckte Regeln gefunden und ausgenutzt werden. Aikidos AI-Pentest kann Cache-Poisoning- und Cache-Deception-Angriffe automatisch erkennen, so wie er dieses Problem gefunden hat.
Wichtige Erkenntnisse
- Am 20. Januar 2026 hat Aikidos AI-Pentest-System etwas Interessantes in SvelteKit-Anwendungen, die auf Vercel bereitgestellt wurden, gemeldet.
- Wir bestätigten, dass es sich um eine Cache-Deception-Schwachstelle handelte, die Standardkonfigurationen betraf.
- Keine Fehlkonfiguration erforderlich. Nur SvelteKit + Vercel, die tun, was sie sollen.
- Auswirkung: Authentifizierte Antworten können gecacht und anderen Benutzern zugänglich gemacht werden.
- Jede SvelteKit-App, die auf Vercel mit geschützten Endpunkten läuft, kann betroffen sein.
So prüfen Sie, ob Sie betroffen sind
Mit Aikido:
Wenn Sie ein Aikido-Benutzer sind, überprüfen Sie Ihren zentralen Feed. Sie können das Problem in Aikido Intel hier einsehen. Tipp: Aikido scannt Ihre Repositories nächtlich erneut, wir empfehlen jedoch, auch einen vollständigen Rescan auszulösen.
Wenn Sie noch kein Aikido-Benutzer sind, richten Sie ein Konto ein und verbinden Sie Ihre Repos. Unsere proprietäre Malware-Abdeckung ist im kostenlosen Plan enthalten (keine Kreditkarte erforderlich).
Aikidos AI-Pentest und Web-Security-Scanning erkennen Cache-Deception-Flows und unsicheres Rewrite-Verhalten automatisch.
Status des Fixes
Wir haben dies Vercel am 21. Januar 2026 offengelegt.
Zeitplan
- 20. Januar 2026: Aikido Security identifizierte die Schwachstelle, erstellte einen funktionierenden PoC
- 21. Januar 2026: Verantwortliche Offenlegung an Vercel
- 23. Januar 2026: Bericht triagiert
- 9. Februar 2026: Vercel bestätigt den Bericht und beginnt mit der Arbeit an einem Fix
- 19. Februar 2026: Vercel hat die Schwachstelle für alle Benutzer behoben, und eine Advisory wurde veröffentlicht (GHSA-9pq4-5hcf-288c). Das Problem kann in Aikidos Intel-Datenbank eingesehen werden und hat die reservierte CVE-Nummer: CVE-2026-27118.
Wir haben auch ein separates Problem gefunden, das eine Denial of Service in einer experimentellen Funktion von SvelteKit ermöglicht. Dies wurde ebenfalls offengelegt und behoben.

