Zurück zu allen Beiträgen
Veröffentlicht am · von Renaud Deraison

Das Token entkam aus dem Prozess nebenan

Forscher haben ein JWT aus einem benachbarten Cloudflare Worker gezogen, mit 12 Bit pro Sekunde, ohne Sandbox-Ausbruch und ohne Speicherfehler. Die Isolate-Grenze hat gehalten. Das Geheimnis hat sie trotzdem überquert, durch die Hardware darunter. Cloud-Plattformen bieten inzwischen genau diese Grenze an, um von KI-Agenten geschriebenen Code auszuführen. Bromure Agentic Coding greift eine Schicht tiefer und hält Ihre Credentials vollständig aus der Box heraus.

Das JavaScript eines Tenants stellte der CPU ein paar Millionen sorgfältig geformte Fragen und las aus den Antworten das Authentifizierungs-Token eines anderen Tenants. Es blieb die ganze Zeit innerhalb der Grenze, die die Plattform für es gezogen hatte, es lief als gewöhnliches JavaScript, und die Grenze hat durchgehend ihre Arbeit getan.

Am 17. August veröffentlichte ein Forscherteam Remote-Timer-as-a-Service, und am 19. legte Cloudflare den eigenen Bericht dazu nach. Sie zogen ein JSON Web Token, jene signierte Zeichenkette, die ein Dienst als Beweis Ihrer Identität akzeptiert, aus einem co-lokalisierten Cloudflare Worker in Produktion, mit bis zu 12 Bit pro Sekunde bei 99,16 % Genauigkeit. Das vorherige öffentliche Ergebnis gegen dieselbe Plattform, von 2021, schaffte 2 Bit pro Minute. Beim 360-Fachen dieser Rate überschreiten Sie die Linie zwischen einer Kuriosität und einem gestohlenen Credential.

Cloudflare hat den Fehler behoben, in drei Jahren keinen Hinweis darauf gefunden, dass ihn jemand sonst genutzt hätte, und sagt, es seien keine Kundendaten abgeflossen. Lesen Sie darüber hinaus und schauen Sie an, was der Angriff nie tun musste.

Nichts musste brechen

Cloudflare Workers betreibt viele Tenants auf wenig Hardware, und es schafft das, indem es genau das weglässt, was sie sonst trennt. In Cloudflares eigenen Worten führt Workers „Code mehrerer Tenants in getrennten V8-Isolates innerhalb desselben Betriebssystemprozesses aus“. Ein Isolate ist ein Container auf JavaScript-Ebene: eigener Heap, eigene Globals, kein Shared Memory, keine Threads. Es startet in Millisekunden, und genau darum geht es, denn Prozessisolation kostet Sie bei jedem Request einen Cold Start.

Der Angreifer braucht Code, der in einem Isolate läuft. Das Opfer in denselben Prozess zu holen ist der elegante Teil: der Worker des Angreifers ruft das Opfer auf. Wie die Forscher schreiben, führt das Aufrufen des Opfers aus dem Skript des Angreifers mit fetch("https://victim.example") „in den meisten Fällen dazu, dass der Scheduler eine Instanz des Opfer-Workers in exakt demselben Prozess hochfährt“. Man wartet nicht auf Co-Lokation, man beschwört sie herbei.

Ab da ist der Angriff Spectre. Einen Branch Predictor fehltrainieren, damit die CPU spekulativ einen Read ausführt, den sie nie hätte machen dürfen, und dann den Cache messen, um zu erfahren, was sie gelesen hat. Cloudflare hatte bereits Jahre darauf verwendet, das schwer zu machen: kein SharedArrayBuffer, keine Threads, eingefrorene und vergröberte Timer, damit Sie nichts so Kleines wie einen Cache-Treffer messen können, und Dynamic Process Isolation (DyPrIs), das Hardware-Performance-Counter beobachtet und alles, was nach Spectre riecht, in einen eigenen Prozess schiebt.

Die Forscher sind um jede einzelne dieser Maßnahmen herumgegangen.

Die Uhr kam von draußen. Ein WebSocket zu einem Durable Object oder zu einem gewöhnlichen Zeitstempel-Server im Internet liefert Ihnen Sub-Millisekunden-Auflösung von einer Plattform, die sich weigert, Ihnen eine Uhr zu geben. Dann verstärkten sie das Signal, statt es aufzulösen: die Tree-PLRU-Ersetzungsstrategie des L1-Caches folgt Binärbaum-Zeigern, sodass sich ein einzelnes Cache-Ereignis in eine lange Reihe von Treffern oder eine lange Reihe von Fehlschlägen verwandeln lässt. „Das Timing eines einzelnen Cache-Ereignisses kann beliebig verstärkt werden“, schreiben sie. Eine unscharfe Uhr genügt, wenn Sie das, was Sie messen, riesig machen.

DyPrIs hat es gleich zweifach verfehlt. Es isoliert ein Skript nachdem die Invocation beendet ist, und ein Durable Object, das durch Keep-alive-Nachrichten am Leben gehalten wird, läuft stundenlang, bis zu einem Tag, sodass der Exploit innerhalb einer einzigen Invocation fertig wird, die nie endet. Außerdem normalisiert es Branch-Mispredictions über iTLB-Zugriffe, während, in Cloudflares Worten, „unser Remote-Timer eine große I/O-Schleife ist, und dieser WebSocket-Verkehr die iTLB-Aktivität aufbläht“. Die Forscher haben ihren eigenen Nenner wachsen lassen, bis der Alarm normal anzeigte.

Der Rest ist Installationsarbeit: ein spekulatives Type-Confusion-Gadget, um die Root-Adresse des Isolates zu leaken, 64-Bit-Pointer-Confusion auf dem Backing Store eines Typed Array, um daraus einen beliebigen Read zu machen, und dann das JWT des Opfers, Bit für Bit.

Ein OS-Prozess. Zwei Tenants. Eine Grenze aus JavaScript.BetriebssystemprozessAngreifer-Isolatefetch("https://victim.example")holt das Opfer in diesen Prozessnormales JavaScript, kein nativer CodeOpfer-Isolateeigener Heap, eigene Globalskein Shared Memory, keine ThreadsJWT in seinem Adressraumdie Uhr, von draußenWebSocket zu einem ZeitserverSub-Millisekunden-Auflösungdie Plattform-Timer bleiben eingefrorengeteilte CPU: Branch Predictor, L1-Cache, Tree-PLRU-Ersetzungdie Isolate-Grenze existiert hier unten nicht — ein Cache-Ereignis wird zu einer Serie verstärkt, lang genug für eine unscharfe UhrERGEBNIS: das JWT des Opfers, Bit für Bit — bis zu 12 Bit/s bei 99,16 % Genauigkeit, 360× die Rate von 2021
Der Angreifer verlässt sein eigenes Isolate nie. Er ruft das Opfer auf, damit der Scheduler es in denselben Prozess legt, borgt sich eine Uhr von einem WebSocket außerhalb der Plattform, verstärkt ein einzelnes Cache-Ereignis zu einer messbaren Serie und liest das Token des Nachbarn Bit für Bit durch die Hardware, die sich beide Isolates teilen.

Die Fixes sagen mehr als der Fund

Cloudflare hat drei Mitigationen ausgeliefert. Lesen Sie sie zusammen.

Sie haben die V8 Sandbox integriert, die rohe 64-Bit-Zeiger aus der Region des JavaScript-Heaps entfernt und das Typed-Array-Gadget tötet. Sie haben DyPrIs beigebracht, langlebige Durable Objects und I/O-lastige Workloads als vollwertige Sicherheitsfälle zu behandeln statt als Rauschen. Und sie haben Memory Protection Keys ausgerollt, die den Heap jedes Tenants hinter eine hardwaredurchgesetzte Zugriffsgrenze innerhalb des geteilten Prozesses legen.

Alle drei greifen unter JavaScript nach etwas Festerem als JavaScript-Semantik, und die dritte landet auf der CPU selbst. Cloudflare sagt offen, die V8 Sandbox sei „keine vollständige Spectre-Mitigation“. Ingenieure, die eine Grenze auf Sprachebene reparieren, indem sie eine Grenze auf Hardwareebene hinzufügen, haben Ihnen gesagt, wo sie die echte Linie vermuten.

Ein Blog über Agentic Coding, der über ein CDN schreibt

Das Isolate hat das CDN verlassen. Im März hat Cloudflare Dynamic Workers unter dem Titel Sandboxing AI agents, 100x faster ausgeliefert, eine Möglichkeit, zur Laufzeit einen Worker mit Code hochzufahren, den es eine Sekunde vorher noch nicht gab. Wenn Sie je einen Agenten laufen ließen, der eigene Skripte schreibt und ausführt, kennen Sie die Motivation: „wenn ein Agent (oder ein MCP-Server) von einer KI on-the-fly generierten Code ausführen soll, um Aufgaben zu erledigen, muss dieser Code irgendwo laufen“, und „Sie können KI-generierten Code nicht einfach direkt in Ihrer App mit eval() ausführen“.

Cloudflare benennt den Mechanismus im selben Beitrag: „Dynamic Workers nutzen denselben zugrunde liegenden Sandboxing-Mechanismus, auf dem die gesamte Cloudflare Workers-Plattform seit ihrem Start vor acht Jahren aufgebaut ist: Isolates.“ Der Grund ist Geschwindigkeit. Ein Isolate startet in wenigen Millisekunden auf wenigen Megabyte, rund 100-mal schneller und 10- bis 100-mal speichereffizienter als ein Container, sodass eine frische Sandbox pro Request bezahlbar wird statt eines lauwarmen Pools, den Sie wiederverwenden und mit jedem Turn schwächen.

Cloudflare ist offen über den Preis. Der eigene Beta-Beitrag sagt es in acht Worten: „V8-Sicherheitsfehler sind häufiger als Hypervisor-Schwachstellen.“ Sie haben das Monate geschrieben, bevor irgendwer ein Token leakte.

Die Geschichte hier ist also ein Tausch, aufgeschrieben von den Leuten, die ihn machen, und jetzt von Forschern auf 12 Bit pro Sekunde beziffert. Die Frage landet bei allen anderen. Wenn der Code, der da sandboxed wird, von einem Modell geschrieben wurde, geformt von dem, was ein Paket oder eine Webseite ihm erzählt hat, und neben einem Bearer-Token weiterläuft: ist das der Tausch, den Sie wollen?

Bromure zieht die Linie am Hypervisor

Bromure Agentic Coding lässt Ihren Agenten nicht in einem Container auf Sprachebene neben dem Code anderer Leute laufen. Jeder Workspace ist eine virtuelle Linux-Maschine auf Apples Virtualization.framework, ausschließlich Apple Silicon: eigener Kernel, eigener Gastspeicher, eigene Disk, geklont aus einem schreibgeschützten Basis-Image. Kein geteilter Prozess heißt kein Co-Tenant, den man herbeirufen könnte, und die Grenze, hinter der Ihr Agent läuft, ist der Hypervisor, also die Seite von Cloudflares eigenem Vergleich mit den selteneren Bugs.

Das ist die Architektur. Was genau diesen Angriff gegenstandslos gemacht hätte, ist enger, und es sitzt einen Schritt weiter innen.

Das Token war nie in der Box

Was die Forscher mitgenommen haben, war ein JWT, das im Adressraum des Opfers lag, also dort, wo ein laufender Dienst das Credential aufbewahrt, das er benutzt. Sie bekamen weder Shell noch Root.

Ein Bromure-Workspace bewahrt das Credential nicht dort auf.

Jedes Geheimnis eines Profils bleibt auf Ihrem Mac. Das gilt für den ANTHROPIC_API_KEY, das persönliche GitHub-Access-Token, den AWS-Access-Key, das Bearer-Token der kubeconfig, den Basic-Auth-Blob der Container-Registry und den Linear-Key. Was Bromure in die VM injiziert, ist eine Attrappe: ein brm_…-Platzhalter, ein Wegwerf-Client-Zertifikat, ein abgeleiteter Basic-String. Der Agent liest ihn, das SDK liest ihn, git, kubectl und doctl lesen ihn, und die Arbeit geht durch, weil der MITM-Proxy auf dem Host den echten Wert im ausgehenden Request einsetzt. Bei AWS kommt noch eine Umdrehung dazu. Der Host signiert den SigV4-Request mit dem echten Material neu, sodass alles, was am Proxy vorbeiläuft, von Amazon eine InvalidSignatureException zurückbekommt statt eines funktionierenden Aufrufs.

Ein Angreifer mit einem perfekten beliebigen Read in dieser VM, also genau der Primitive, an der die Forscher ein ganzes Paper lang gebaut haben, liest damit einen Köder. Die Bytes sind da, sie parsen, sie sehen aus wie ein Schlüssel, und sie kaufen nichts außerhalb der Maschine. Das gilt unabhängig davon, ob die Isolationsgrenze makellos ist, denn der Workspace ist leer von dem, was zu stehlen sich lohnt.

KONVENTIONELL: die Grenze ist Software, und das Geheimnis liegt darinAgent-Code in einem Isolateteilt sich einen Prozess mit anderen TenantsECHTES TOKEN in seinem Adressraumdie geteilte Hardware darunterCache und Branch Predictortragen die Bits, die die Grenze blockteder Nachbarliest das Token12 Bit/s, 99,16 %BROMURE: die Grenze ist der Hypervisor, das Geheimnis liegt jenseits davondie Workspace-VMeigener Kernel, eigener Speicher, keine Co-TenantsANTHROPIC_API_KEY=brm_…eine Attrappe — ein beliebiger Read liest einen KöderMITM-Proxy, host-seitigtauscht die Attrappe gegen den echten WertEgress-Regeln bestimmen, wohin Bytes dürfenoptionaler Zustimmungsdialog pro Nutzungdie echte APIsieht die echteCredential, gesendetvon Ihrem Macjeder Tausch, jede erlaubte und verweigerte Verbindung: eine Zeile in Window → Security Timeline, außerhalb der VM geschrieben
Konventionell ist die Sandbox-Grenze das Einzige zwischen einem Nachbarn und Ihrem Credential, und das Credential liegt in der Sandbox. In einem Bromure-Workspace ist die Grenze der Hypervisor, und das Credential liegt auf der anderen Seite davon: der Gast hält eine Attrappe, und ein Proxy, den der Gast nicht erreichen kann, setzt den echten Wert auf der Leitung ein.

Zwölf Bit pro Sekunde brauchen immer noch einen Weg nach draußen

Ein Seitenkanal ist die halbe Exfiltration. Die andere Hälfte ist eine Route nach draußen, und 12 Bit pro Sekunde sind eine Route, die eine Weile offen bleiben muss. Ein Token mit 400 Zeichen bedeutet Minuten an Verkehr zu einem Ziel, das der Angreifer kontrolliert.

Ein Bromure-Profil bringt eigene Egress-Regeln mit, geschrieben als kurze Policy im pf-Stil und als Tabelle bearbeitet. Ihr Mac setzt sie durch, im virtuellen Switch und im Proxy, und nichts im Gast hat dabei ein Wort mitzureden: eine verweigerte Verbindung bekommt ein Reset, und die Entscheidung landet als egress.firewall-Zeile in Window → Security Timeline mit Host, IP, Port und Verdikt. Code, der im Workspace läuft, sitzt auf der falschen Seite der Regeln, die er ändern müsste.

Sie können auch bei jeder Ausgabe eines echten Credentials die Hand aufhalten. Schalten Sie Require approval to use pro Secret ein: die API-Keys der Modelle, das SSH-Signieren, die Tokens von GitHub, GitLab und Bitbucket, jeder kubeconfig-Kontext, DigitalOcean, jede AWS-SigV4-Signatur, jede Container-Registry und jede manuelle Token-Regel, die Sie hinzufügen. Der Tausch pausiert dann für einen Dialog auf macOS, und Sie erteilen ihn für fünf Minuten, eine Stunde oder die Sitzung. Der Gast kommt nie dazu, diese Frage zu beantworten.

Der Tausch ist die Geschichte

Isolates sind ein gutes Stück Engineering, und Cloudflare hat das so gehandhabt, wie man es sich wünscht: koordinierte Offenlegung, drei echte Mitigationen, kein Herumreden darüber, was die V8 Sandbox abdeckt und was nicht. Millionen Requests pro Sekunde laufen nicht ohne Grund nicht auf Containern.

Cold Starts haben das Argument auf einem CDN gewonnen, und Ihr Coding-Agent beantwortet keinen HTTP-Request in vier Millisekunden. Er läuft eine Stunde, installiert Pakete, die niemand auditiert hat, führt Testsuiten aus, die ein Modell geschrieben hat, und liest Webseiten, die gern ein Wörtchen mit ihm reden würden. Was auch immer diesen Workload ausführt, hält für die gesamte Dauer Ihre Tokens, und das Einzige, was Sie über den Code wissen, den es ausführt, ist, dass Sie ihn nicht geschrieben haben.

Für diesen Job sind ein paar hundert Millisekunden VM-Boot keine Kosten, die sich zu optimieren lohnen. Cloudflare hat den Wechselkurs schon veröffentlicht: V8-Bugs sind häufiger als Hypervisor-Bugs. Bromure nimmt die andere Seite dieses Tauschs, und holt dann auch noch das Token aus dem Raum.


Quellen: Schwarzl, Xiao, Pedersen, Ainsworth, Topham, „Remote-Timer-as-a-Service: Efficient Microarchitectural Leakage in the Cloud with Remote Timers“ (arXiv:2608.17043, 17. August 2026) · Cloudflare, „A revisit of remote Spectre attacks on Cloudflare Workers“ (19. August 2026) · Cloudflare, „Sandboxing AI agents, 100x faster“ (24. März 2026) · The Hacker News, „Cloudflare Workers Spectre Attack Leaks JWT From Co-Located Worker at 12 Bits/Second“ (19. August 2026)