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

Der freie Platz war nicht leer

Am 24. September haben Cloudflare und Oren Yomtov von Accomplish eine mandantenübergreifende Lücke in Cloudflare Containers und Sandboxes veröffentlicht. Schreiben Sie 4 KiB in eine frische Sandbox, lesen Sie die rohe Platte, und die anderen 60 KiB des Blocks kommen zurück und enthalten die .env-Dateien, Zugangsdaten-Dateien und Chromium-Profile des vorherigen Mandanten. Nichts ist aus irgendetwas ausgebrochen: jede aktive Grenze hielt, und das Leck lag darin, was mit einem Block geschah, nachdem sein Besitzer mit ihm fertig war. Cloudflare verkauft Sandboxes, um Code auszuführen, den Sprachmodelle erzeugt haben. Bromure Agentic Coding führt diesen Code aus einer Image-Datei auf Ihrem eigenen Mac aus, und die freien Blöcke, aus denen es schöpft, sind Ihre.

Eine Sandbox hat zwei Aufgaben. Einzuschließen, was darin läuft, und zu vergessen, was darin vorher lief. Die zweite ist eine Konfigurationsoption.

Sie schicken die Testsuite des Agenten in eine Cloud-Sandbox, weil es irgendwann im letzten Jahr aufgehört hat, clever zu wirken, ungeprüften Code auf dem eigenen Laptop laufen zu lassen. Die Sandbox steht in etwa einer Sekunde mit einem vollständigen Linux-Dateisystem. Der Agent schreibt eine kleine Datei. Darunter reicht die Plattform ihm einen Plattenblock von 64 Kilobyte, und 60 dieser Kilobyte enthalten noch die .env von jemand anderem.

Sie mussten aus nichts ausbrechen, um dorthin zu kommen.

Schreiben Sie vier Kilobyte, lesen Sie sechzig

Am 24. September hat Cloudflare einen gemeinsamen Bericht mit den Forschern über eine mandantenübergreifende Lücke in Cloudflare Containers veröffentlicht. Oren Yomtov von Accomplish hat sie am 4. September über HackerOne gemeldet und seine eigene Darstellung veröffentlicht, in derselben Woche. The Hacker News berichtete am Tag darauf.

Containers gibt jedem Kunden eine Platte aus einem gemeinsamen Pool, über Linux Device-Mapper Thin Provisioning, mit einer Blockgröße von 64 KiB. Der Pool trug die Option skip_block_zeroing, die genau das tut, was sie sagt: dm-thin löschte einen neu zugewiesenen Block nicht, bevor es ihn an einen Container übergab. Wurde ein Container gelöscht, gingen seine Blöcke mit unverändertem Inhalt in den Pool zurück, und der Pool spannte sich über Kundenkonten hinweg.

Von dort sind es vier Schritte und kein Exploit:

  1. 64-KiB-ausgerichtete Regionen finden, die das ext4-Dateisystem des Containers selbst für frei hält.
  2. Einen einzigen 4-KiB-Block in jede davon schreiben. Das genügt, damit dm-thin einen physischen 64-KiB-Block aus dem gemeinsamen Pool zuweist.
  3. Das rohe Gerät lesen statt des Dateisystems.
  4. Die anderen 60 KiB behalten.

Cloudflares eigener Satz für die Primitive ist der ganze Bug: „ein Schreibvorgang über den vollen Block ersetzte dessen vorherigen Inhalt, aber ein kleinerer Schreibvorgang änderte nur den geschriebenen Teil.“

Die geborgenen Blöcke enthielten nutzbare Struktur. Cloudflare berichtet von „Verzeichnisstrukturen, Datenbankseiten und strukturell vollständigen SQLite-Datenbanken“ und zählt 2.700 verschiedene fremde Verzeichnis-Inodes über sechs Produktions-Placements, mit Restmaterial auf 18 von 24 Placements. The Hacker News berichtet von Daten, die auf 20 von 22 zugrunde liegenden Maschinen auf vier Kontinenten geborgen wurden. Yomtov listet auf, was er von diesen Blöcken gelesen hat: „Verzeichnislistings, SQLite-Datenbanken, Chromium-Profile, .env-Dateien und Zugangsdaten-Dateien.“

Cloudflare nennt zwei Grenzen, die den Vorfall einfassen. Ein Angreifer „konnte kein bestimmtes Opfer auswählen und nicht auf eine aktiv angehängte Platte zugreifen“ — Sie bekamen also, wer auch immer auf dieser Maschine gewesen war, und kein selbst gewähltes Ziel. Und Cloudflare hat aus dem Proof of Concept der Forscher Erkennungssignaturen gebaut, sie gegen die historische Telemetrie der Plattenaktivität laufen lassen und „keinen Hinweis darauf gefunden, dass dieser spezifische Angriffsvektor von jemand anderem ausgenutzt wurde.“

Cloudflare war schnell. Meldung um 15:26 UTC am 4. September; Fehlkonfiguration in der Produktion um 18:45 bestätigt; Runtime-Fix um 21:27 gemergt; Pool-Konfiguration um 22:03 gemergt; Rollout um 23:15 gestartet. Alles davon innerhalb eines Tages. Der Rollout war am 7. September abgeschlossen, die Forscher bestätigten am 14. September, dass ihr Proof of Concept tot war, und Cloudflare räumte am 19. September die letzten Platten-Snapshots aus der Zeit vor der Mitigation weg. Kunden hatten nichts zu tun — und keine Möglichkeit, von innerhalb einer Sandbox zu prüfen, ob ihre eigenen Blöcke sauber angekommen waren.

Ein Pool aus 64-KiB-Blöcken, zwei Kunden, kein NullenContainer, Kunde A.envZugangsdatensqlite-Seiten, chromium-Profilgelöscht — Blöcke zurück in den PoolSandbox, Kunde B4 KiB in freien Platz schreiben/dev/vdc lesen, nicht das fsbehält die anderen 60 KiBein Workers-Paid-Konto, nicht mehrGemeinsamer dm-thin-Pool — 64-KiB-Blöcke, über Kundenkonten hinwegskip_block_zeroing — ein freigegebener Block wird mit intaktem Inhalt neu vergebenDer Block, den Kunde B bekam4 KiB geschrieben60 KiB von wer auch immer vorher hier wardas fs nennt das freien Platz; das rohe Gerät sieht es anders
Ein 4-KiB-Schreibvorgang, ein 64-KiB-Block. Cloudflare Containers weist Plattenplatz aus einem gemeinsamen Device-Mapper-Thin-Pool mit einer Blockgröße von 64 KiB zu, und der Pool war mit skip_block_zeroing konfiguriert, sodass ein von einem Kunden freigegebener Block mit unverändertem Inhalt in den Pool zurückging. 4 KiB in eine Region zu schreiben, die das ext4-Dateisystem des Containers selbst für frei hielt, löste die Zuweisung eines dieser Blöcke aus; das rohe Gerät statt des Dateisystems zu lesen gab die anderen 60 KiB zurück. Die Forscher zählten 2.700 verschiedene fremde Verzeichnis-Inodes über sechs Produktions-Placements, und was sie lasen, umfasste .env-Dateien, Zugangsdaten-Dateien, SQLite-Datenbanken und Chromium-Profile.

Jede aktive Grenze hielt

Der Titel von Yomtovs Bericht, „Escaping the Cloudflare Sandbox“, verkauft unter Wert, wie leise dieser Bug ist.

Er fand keinen Speichersicherheitsfehler, keine Privilegieneskalation und keinen Container-Ausbruch. Jede Grenze um einen laufenden Container hielt für die Dauer des Vorfalls wie entworfen. Kunde B konnte den lebenden Container von Kunde A nicht lesen, und Cloudflare weist darauf hin, dass eine Sandbox auch keine aktiv angehängte Platte erreichen konnte.

Das Leck saß in der Übergabe. Cloudflare gab einen Block von einem Mandanten frei und reichte ihn an den nächsten, und was zwischen diesen beiden Kunden stand, war ein Boolean in einer Pool-Konfiguration.

Forscher richten ihre Aufmerksamkeit darauf, was der Code in einer Sandbox jetzt gerade erreichen kann, und viel weniger darauf, was der letzte Bewohner hinterlassen hat. Diese zweite Frage hat meistens eine langweilige Antwort: die Plattform nullt den Block. Die Antwort hält, bis ein Ingenieur das Nullen aus Durchsatzgründen abschaltet.

Accomplish zählt das als seinen sechsten veröffentlichten Sandbox-Ausbruch seit Juli 2026. Die vorherigen fünf: SharedRoot in Claude Cowork, Beltdown in Claude Code, Beltdown2 in Cursors CLI, einer im VMM von Docker und einer in OpenAIs Codex-Sandbox. Fünf dieser sechs führen Code aus, den ein Agent geschrieben hat. Yomtovs eigenes Fazit ist eine Zeile lang: „Isolation kann auf viele Weisen scheitern.“

Genau hierher sollte der Code der Agenten wandern

Cloudflare Sandboxes läuft auf Containers und hat den Bug damit geerbt. Sandboxes ist außerdem das Produkt, das Cloudflare für genau die Sache verkauft, über die dieses Blog immer weiter schreibt. Aus Cloudflares eigener Dokumentation: das SDK existiert, um „nicht vertrauenswürdigen Code sicher in isolierten Umgebungen auszuführen“, es dient dazu, „von großen Sprachmodellen erzeugten Code sicher und zuverlässig auszuführen“, und es passt für „KI-Agenten, Code-Assistenten und autonome Systeme, die nicht vertrauenswürdigen Code ausführen müssen.“ Jede Sandbox läuft „in ihrem eigenen isolierten Container mit einer vollständigen Linux-Umgebung und bietet starke Sicherheitsgrenzen bei gleichbleibender Performance.“

Jeder Teilsatz davon ist etwas, das man vernünftigerweise will, und er beschreibt die Bromure-Workspace-VM etwa so gut, wie er eine Cloudflare Sandbox beschreibt. Der Unterschied ist, wer sonst auf der Maschine ist.

Die Ausführung der Agenten von Ihrem Laptop wegzuschieben verlagert eine Vertrauensentscheidung, es entfernt sie nicht. Sie vertrauen jetzt einem Pool-Allokator, den Sie nicht sehen können, in einem Placement, das Sie nicht gewählt haben, neben Mandanten, die niemand für Sie benennen wird. Das kann der richtige Handel sein. Gehen Sie ihn absichtlich ein, und stellen Sie zuerst die Frage nach dem Rückstand: woher kommen meine freien Blöcke, und was war darin.

Die Platte ist eine Datei auf Ihrem Mac

Bromure Agentic Coding beantwortet diese Frage, indem es keinen Pool hat.

Jeder Workspace bildet auf genau eine VM ab. Zwei Workspaces teilen sich nie eine VM, und ein Workspace hat nie zwei. Die VM bootet von zwei virtuellen Platten, die gewöhnliche Dateien im eigenen Verzeichnis dieses Workspace auf Ihrem Mac sind. disk.img ist die Systemplatte, beim ersten Start als APFS-Copy-on-Write-Klon des lokalen Ubuntu-Basis-Images erzeugt: sofort da, und kostenlos, bis der Gast schreibt. home.img ist ein privates, sparse ext4-Image, das /home/ubuntu hält und als zweites virtio-blk-Gerät angehängt ist.

Die Vier-Schritte-Technik hat hier nichts, worauf sie landen könnte. Ein Agent im Gast kann das rohe Blockgerät statt des Dateisystems lesen, weil er dort drin root ist, und das ist in Ordnung. Er erreicht eine Image-Datei, die zu einem Workspace gehört. Die Blöcke, in die diese Datei hineinwächst, kommen vom APFS-Volume Ihres eigenen Mac, und der vorherige Bewohner eines freien Blocks auf Ihrem Mac waren Sie.

Ein Objekt wird zwischen Workspaces geteilt, und „nichts wird geteilt“ wäre die falsche Behauptung, also benennen wir es: jede Workspace-Platte wird von base.img geklont. Ubuntu 24.04, 24 GB logisch und 6 bis 8 GB physisch, gegen einen signierten Image-Katalog geholt, der eine ed25519-Signatur mit demselben Schlüssel trägt, der die App-Updates signiert, und der die Identität des Images, seinen SHA-256 und jeden Postinstall-Befehl abdeckt, mit Rollback-Schutz und Ablehnung unsignierter Kataloge. Es ist auf jeder Installation byteidentisch und enthält nichts von Ihnen. Das ist die richtige Art von Sache, die man teilt: ein öffentliches Artefakt, dessen Aufgabe es ist, überall identisch zu sein.

Ein Multi-Tenant-PlacementKunde AKunde B…und alle anderenein Pool aus 64-KiB-Blöckenein freigegebener Block geht an den Nächstensauber bei Ankunft: eine Einstellung, keine Garantiewas in den Blöcken war.env, Zugangsdaten-Dateiensqlite-Datenbanken, chromium-Profile2.700 fremde Verzeichnis-Inodes über sechs Placements;Rückstand auf 18 von 24. Keine Kundenaktion möglich.Bromure Agentic Coding, auf Ihrem Macbase.imgUbuntu 24.04, signierter Katalog, überall identisch, nichts von IhnenWorkspace einsdisk.img — CoW-Klonhome.img — privates ext4Workspace zweidisk.img — CoW-Klonhome.img — privates ext4was in diesen Blöcken stehtghp_… und sk-ant-api03-brm-… — PlatzhalterFreie Blöcke kommen von Ihrem Volume. Die echten Geheimnisseliegen im Host-Proxy und werden beim Hinausgehen eingesetzt.
Zwei Antworten auf dieselbe Frage. Auf einem Multi-Tenant-Placement ist die Platte einer Sandbox ein Pachtvertrag auf Blöcke aus einem Pool, der mit Kunden geteilt wird, von denen man Ihnen nichts erzählt, und ob diese Blöcke sauber ankommen, ist eine Eigenschaft der Plattformkonfiguration. In Bromure Agentic Coding ist die Systemplatte des Workspace ein APFS-Copy-on-Write-Klon eines signierten, byteidentischen öffentlichen Basis-Images, sein Home ist ein privates sparse ext4-Image, beide sind Dateien im eigenen Verzeichnis dieses Workspace, und die freien Blöcke, in die sie hineinwachsen, kommen von Ihrem eigenen Volume. Der zweite Unterschied ist, was in diese Blöcke geschrieben wird: die geborgenen Artefakte im Cloudflare-Fall waren .env- und Zugangsdaten-Dateien, und in einem Bromure-Gast enthalten diese strukturerhaltende Fälschungen, während die echten Werte im Host-Proxy auf dem Mac bleiben.

Und der Rückstand wäre wertlos

Das Blocklayout ist die halbe Antwort. Die andere Hälfte ist, was ein Coding-Agent auf die Platte schreibt — und genau das machte diesen Bug meldenswert: .env-Dateien, Zugangsdaten-Dateien, Chromium-Profile.

In einem Bromure-Workspace existieren diese Dateien, und die Werkzeuge, die sie lesen, funktionieren wie immer, aber die Werte darin sind falsch. Keine Datei, keine Umgebungsvariable und kein Prozess in der VM hält jemals einen echten API-Schlüssel, ein echtes OAuth-Token, ein echtes AWS-Secret oder einen echten privaten SSH-Schlüssel. Der Gast bekommt stattdessen strukturerhaltende Platzhalter: sk-ant-api03-brm-…, ein GitHub-Token in ghp_-Form, brm_…, pro Installation deterministisch, damit clientseitige Validierer zufrieden sind und kein Werkzeug je denkt, ein Schlüssel sei zwischen zwei Sitzungen rotiert worden. Die echten Werte leben in der In-Memory-Tauschtabelle des Host-Proxys auf dem Mac, jeder an den Ziel-Host gebunden, zu dem er gehört, und werden auf dem Weg nach draußen eingesetzt, mit einem Scoping, das exakt-oder-Subdomain ist, niemals Teilstring. AWS-Anfragen werden host-seitig neu signiert: der Gast signiert mit einem falschen Secret, der Host entfernt diese Signatur und signiert neu. SSH läuft signatur-only über eine vsock-Brücke, und die Bytes privater Schlüssel gelangen überhaupt nie in den Gast.

Das Chromium-Profil behandelt Bromure separat. Das Browser-Panel, das der Agent steuert, läuft in seiner eigenen flüchtigen Alpine-VM, einem Copy-on-Write-Klon im temporären Verzeichnis, das die App löscht, wenn Sie das Panel abbauen. Logins zu behalten ist Opt-in, und dann liegt das Profil auf einer verschlüsselten Platte pro Workspace.

Würde irgendein künftiger Fehler die Blöcke eines Bromure-Gasts offenlegen, käme der Leser mit einem Verzeichnisbaum davon, mit Quellcode, den Sie schon haben, und mit einer Zugangsdaten-Datei, die nirgends ausgegeben werden kann.

Wegwerfbarkeit als Verb

Workspaces sind absichtlich persistent. Programmieren braucht dauerhaften Zustand: geklonte Repos, Paket-Caches, Toolchains, Shell-History. Also kontrolliert Bromure, was die VM halten darf, statt sie jede Nacht zu zerstören, und eine Platte zu löschen ist etwas, um das Sie bitten. Die App ist deutlich bei jeder Art zu bitten:

Auf Basis zurücksetzen

Löscht disk.img, sodass der nächste Start eine frische Kopie des Basis-Images neu klont. Der Dialog benennt, was geht: alles, was Sie mit apt install installiert haben, und Ihre Änderungen an /etc, /var, /usr, /opt. Home überlebt.

Home löschen, Workspace löschen

Home löschen wirft /home/ubuntu und das erzeugte Schlüsselpaar weg. Den Workspace zu löschen entfernt das ganze Profilverzeichnis, beide Images, die verschlüsselte Secrets-Datei, jeden Checkpoint und das host-seitige SSH-Material und gibt dann seine reservierte MAC-Adresse frei.

Wegwerf-VMs und Checkpoints

bromure-cli vm run --rm gibt Ihnen einen Workspace im Docker-Stil, der gelöscht wird, wenn die VM stoppt. Jeder erfolgreiche Boot lässt einen Copy-on-Write-Checkpoint von Platte und Home zurück, aufgenommen erst nach einem Boot, der ein funktionierendes Terminal ergab, also ist jeder davon erwiesen bootfähig.

Das erzwungene Löschen

Erwischt der Proxy einen Platzhalter als Zugangsdatum auf dem Weg dorthin, wo er nicht hingehört, markiert Bromure den Workspace als kompromittiert, und er bootet nicht wieder, bis Sie seine Platte und sein Home löschen. Ihre Einstellungen, Tokens und SSH-Schlüssel bleiben, und das Löschen berührt nie gemeinsame Host-Ordner.

Dieser Satz von Verben ist der Unterschied zwischen einer Löschung, um die Sie gebeten haben, und einer Löschung, die Sie angenommen haben.

Fragen Sie, was der letzte Mieter hinterlassen hat

Cloudflare hat die Fehlkonfiguration gefunden, sie in neun Stunden behoben, die Pools und die Snapshots geräumt, Erkennungssignaturen gebaut, um die Vergangenheit zu prüfen, und die Blockgröße und den Namen des Flags veröffentlicht. Lesen Sie das als einen Anbieter, der einen schlechten Tag gut handhabt.

„Sandbox“ benennt eine Hoffnung über eine Grenze, und diese Grenze stellte sich als Lebenszyklus einer Ressource heraus statt als Mauer. Die Antwort der Branche auf Agenten, die ungeprüften Code ausführen, war, die Ausführung irgendwo anders hin zu verlegen und darauf zu vertrauen, dass dieses Irgendwo-anders sauber ankommt. Es kommt sauber an, meistens. Prüfen können Sie es von innerhalb der Sandbox nicht, diese Woche nicht und in keiner anderen.

Lassen Sie den Code auf Infrastruktur laufen, die Sie sehen können, und Sie dürfen die Frage nach dem Rückstand selbst beantworten: eine Image-Datei pro Workspace, freie Blöcke von Ihrem eigenen Volume, ein geteiltes Objekt, und das ist ein signiertes öffentliches Basis-Image, und nichts auf dieser Platte, das lesenswert wäre, falls sie doch einmal leckt. Sie zu löschen ist ein Menüpunkt.