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

Der Service Worker, der nicht sterben will, und die VM, der das egal ist

Google hat letzte Woche versehentlich einen vier Jahre alten Chromium-Bug erneut veröffentlicht — einen Service Worker, der nach dem Schließen des Browsers weiterhin JavaScript ausführt, in jedem großen Chromium-Browser, immer noch ungepatcht. Der Proof-of-Concept kursiert nun frei im Netz. Die interessante Frage ist nicht, wie er funktioniert. Sondern: Was bedeutet „Persistenz“ auf einem Browser, dessen gesamte zugrunde liegende Maschine aufhört zu existieren, sobald Sie den Tab schließen?

Persistenz ist keine Eigenschaft von Code. Sie ist eine Eigenschaft des Ortes, an dem der Code leben darf. Ein Service Worker, der „niemals stirbt", hat ein Problem, wenn die Maschine, auf der er installiert wurde, jedes Mal zerstört wird, sobald Sie das Fenster schließen.

Am 20. Mai 2026 entfernte der Issue-Tracker für Chromium leise die Zugriffsbeschränkungen für einen Bug, der seit 2022 unter restriktivem Status lag. Innerhalb von Stunden wurde der Bug — zusammen mit einem funktionierenden Proof-of-Concept — überall im Web gespiegelt, archiviert und besprochen. Google bewegte sich, um das Issue erneut zu schließen. Es war zu spät; die Seite war bereits in der Wayback Machine, und BleepingComputers Artikel ging am nächsten Tag online.

Der Bug ist real, der Proof-of-Concept funktioniert, und vier Jahre nach seiner ursprünglichen Meldung ist er in Chrome Dev 150 oder Edge 148 immer noch nicht gepatcht. Er betrifft jeden Chromium-basierten Browser: Chrome, Edge, Brave, Opera, Vivaldi, Arc.

Was er einer Seite erlaubt, klingt als Satz banal: Sie registriert einen Service Worker — ein kleines Stück JavaScript, von dem der Browser zustimmt, es im Hintergrund weiterlaufen zu lassen — der nicht aufhört zu laufen, wenn die Seite schließt, wenn der Tab schließt, wenn der Browser schließt, wenn die Maschine neu startet. Die Forscherin Lyra Rebane, die den Bug ursprünglich im Dezember 2022 gemeldet hat, fasste den Worst Case gegenüber BleepingComputer zusammen: bei Microsoft Edge erscheint nicht einmal das Download-Menü, sodass das Ergebnis „völlig stille JS-RCE ist, die selbst nach dem Schließen des Browsers weiterläuft."

Das technische Detail, warum der Bug existiert, ist weniger wichtig als die Klasse von Angriffen, die er ermöglicht. Er ist ein Persistenz-Primitiv. Eine Seite, die Sie einmal besucht haben, möglicherweise vor Monaten, möglicherweise eine Werbeanzeige, an die Sie sich nicht erinnern, darf auf Ihrem Computer unbegrenzt Code ausführen. Botnet-Anmeldung, Werbebetrug, Cryptojacking, DDoS-Beteiligung, langsame Datenexfiltration, opportunistisches Sammeln von Zugangsdaten, sobald Sie sich erneut auf derselben Seite anmelden — all das wird trivial, sobald Sie einen Brückenkopf haben, der das Beenden des Browsers überlebt.

Es ist ein guter Bug, in dem Sinne, dass er erhellend ist. Es ist ein schlechter Bug, in dem Sinne, dass er ausgenutzt werden wird.

Was ein Service Worker eigentlich ist

Die Web-Plattform erlaubt es Seiten seit etwa einem Jahrzehnt, kleine JavaScript-Programme namens Service Worker zu installieren. Sie laufen im Hintergrund, getrennt von jedem Tab, und existieren, damit Web-Apps vernünftige Dinge tun können — Assets zwischenspeichern, damit eine Seite lädt, wenn Sie offline sind, Push-Benachrichtigungen zustellen, Daten synchronisieren, sobald das Netzwerk wieder verfügbar ist.

Ein Service Worker wird gegen einen Origin registriert (etwa die Kombination aus https, dem Hostnamen example.com und dem Standardport). Einmal registriert, speichert der Browser ihn auf der Festplatte und bringt ihn zurück, wenn Sie das nächste Mal irgendetwas auf diesem Origin besuchen — oder, im Falle von Hintergrund-Funktionen wie Push-Nachrichten, weckt ihn periodisch von selbst auf. Aus Sicht des Benutzers ist der Worker unsichtbar. Aus Sicht des Betriebssystems ist der Worker Teil des Browsers und läuft mit den Berechtigungen, die der Browser-Prozess hat.

1. Seite registriert Workernavigator.serviceWorker.register('/sw.js')2. Browser speichert ihnin das Profil auf der Festplatte geschrieben,indiziert nach Origin,beschränkt auf einen URL-Pfad,überlebt Neustarts.3. Browser weckt ihn aufbei Wiederbesuch, bei Push,bei Hintergrund-SyncDAS BROWSER-PROFIL AUF DER FESTPLATTECookies · localStorage · IndexedDB · Service-Worker-Registrierungen— der Ort, an dem „Persistenz" tatsächlich lebt —
Das normale Leben eines Service Workers. Eine Seite registriert ihn, der Browser schreibt ihn auf die Festplatte unter dem Origin der Seite, und von da an ist der Browser dafür verantwortlich, den Worker wieder aufzuwecken — wenn der Nutzer den Origin erneut besucht, wenn ein Push ankommt, wenn ein Hintergrund-Sync auslöst. Die Adresse des Workers ist Ihre lokale Festplatte; die Lebensdauer des Workers ist die Lebensdauer des Browser-Profils, das ihn beherbergt.

Der Bug, den Rebane gemeldet hat, ist grob gesagt der, dass eine feindliche Seite eine Hintergrund-Download-API missbrauchen kann, um einen Worker zu registrieren, den der Browser dann nicht mehr beenden will. Andere Chromium-Service-Worker-Bugs derselben Familie sind schon zuvor ausgeliefert worden; dies ist mindestens der zweite in den letzten zwölf Monaten. Das Muster — die Seite pflanzt etwas ein, der Browser speichert es, der Browser bringt es später von selbst zurück — ist der Teil, den man festhalten sollte. Es ist auch das Muster, das gegen eine Wand läuft, sobald der Browser kein Stück lang lebender Festplatte mehr besitzt.

Was Persistenz benötigt

Persistenz — im Sicherheitssinne, nicht im Sinne der Web-Plattform — ist der Zug, den ein Angreifer unmittelbar nach dem initialen Zugriff macht. Eine Seite oder ein Binärprogramm landet auf Ihrer Maschine und sorgt, bevor es irgendetwas anderes Interessantes tut, dafür, dass ein Teil von sich selbst die offensichtlichen Aufräumschritte überlebt: Tab schließen, Browser beenden, Neustart, das Laptop auf dem Heimweg im Zug in den Ruhezustand versetzen. Auf einem Desktop-OS hat Persistenz ihr eigenes Vokabular — Launch Agents unter macOS, Geplante Aufgaben unter Windows, systemd-User-Units unter Linux, Browser-Erweiterungen, Autostart-Einträge.

Ein Service Worker ist faktisch ein Launch Agent im Browser. Er wird registriert, gespeichert und nach einem Zeitplan, den der Browser kontrolliert, wieder zum Leben erweckt. Er ist eines der eleganteren Persistenz-Primitive, die die Web-Plattform bietet, was teilweise erklärt, warum er immer wieder Bugs anzieht.

Entscheidend ist, dass jede Form von Persistenz in dieser Liste dieselbe Anforderung hat, in drei Worten ausgedrückt: etwas muss bestehen bleiben. Ein Launch Agent bleibt bestehen, weil es ein Dateisystem gibt, auf das die .plist-Datei des Agents geschrieben wird, und der Agent wird bei jedem Bootvorgang von diesem Dateisystem zurückgelesen. Ein Service Worker bleibt bestehen, weil es ein Browser-Profil gibt, auf das die Registrierung des Workers geschrieben wird, und die Registrierung wird bei jedem Browser-Start zurückgelesen. Nehmen Sie die Speicherschicht weg, und die „Persistenz" verschwindet mit ihr.

Dieser Satz — Nehmen Sie die Speicherschicht weg, und die Persistenz verschwindet mit ihr — ist der Teil der Architektur, um den herum Bromure geschrieben wurde.

Wie Bromure einen Browser ausführt

Eine Bromure-Sitzung ist kein Prozess. Sie ist eine virtuelle Maschine. Wenn Sie ein Browser-Fenster öffnen, startet der Host einen kleinen, kurzlebigen Linux-Gast auf dem Hypervisor von Apple Silicon. Der Browser-Prozess innerhalb dieses Gasts ist das, worin Ihre Tabs laufen. Der Gast hat sein eigenes Dateisystem, seinen eigenen Arbeitsspeicher, seinen eigenen Kernel. Nichts davon gehört dem Host.

Es gibt zwei Teile dieser Architektur, die für den Service-Worker-Bug im Besonderen wichtig sind.

Erstens: Das Profil auf der Festplatte, auf dem die Registrierung eines Service Workers normalerweise leben würde, befindet sich im Dateisystem des Gasts, nicht im Dateisystem Ihres Macs. Wenn der Gast verschwindet, geht dieses Dateisystem mit ihm. Zweitens: Der Gast selbst hat eine Lebensdauer, die der Nutzer festlegt — standardmäßig ist ein Gast an ein Profil gebunden (Arbeit, privat, Banking, LLM-Coding-Sandbox) und wird gelöscht, wenn der Nutzer es entscheidet, aber für kurzlebige Tabs wird der Gast zerstört, sobald das Fenster geschlossen wird. Selbst im Profil-Modus ist der Gast ein Festplatten-Volumen-Snapshot, den der Nutzer jederzeit zurückrollen kann.

Traditioneller BrowserIHR BENUTZER · IHRE FESTPLATTETab besucht feindliche Seiteregistriert Service WorkerWorker ins Profil geschrieben~/Library/Application Support/...auf Ihrer echten FestplatteSie schließen den Tab…der Worker bleibt auf der Festplatte…Browser belebt ihn später wiederbeim nächsten Start, bei einem Push, bei einem Sync —das JS läuft weiter. Monatelang.BromureKURZLEBIGE GAST-VMGAST-DATEISYSTEMTab besucht feindliche Seiteregistriert Service WorkerWorker auf Gast-Festplatte geschriebeninnerhalb der VM — nicht auf dem Hostberührt niemals das Dateisystem Ihres MacsSie schließen den TabVM wird zerstörtdie Festplatte des Gasts geht mit ihr.nichts mehr, was wiederbelebt werden könnte.
Derselbe feindliche Service Worker, gegen zwei Browser registriert. In einem traditionellen Browser wird die Registrierung in ein Profil auf der Host-Festplatte des Nutzers geschrieben; das Schließen des Browsers entfernt sie nicht, und der nächste Start bringt den Worker zurück. In Bromure wird die Registrierung in das Dateisystem einer Gast-VM geschrieben; das Schließen des Tabs zerstört die VM, und die Registrierung verschwindet mit ihr.

Im kurzlebigen Fall hat der „nie sterbende" Worker keinen Ort, von dem aus er nicht-sterben könnte. Die Festplattenzeile, von der aus er beim nächsten Browser-Start zurückgelesen worden wäre, lag in einer virtuellen Maschine, die nicht mehr existiert. Das JavaScript, das „nach dem Schließen des Browsers weiterlief", lief nur deshalb weiter, weil es etwas gab, worauf es weiterlaufen konnte. Wenn das Schließen des Browsers auch die zugrunde liegende Maschine schließt, stoppt der Worker zur selben Zeit wie der Browser — genau das Verhalten, das die ursprüngliche Spezifikation annahm.

Im Profil-Fall — sagen wir, Sie pflegen ein langlebiges „Social-Media"-Profil, das Sie zwischen den Sitzungen absichtlich wiedererkennen soll — überlebt der Worker so wie immer, beschränkt auf die VM dieses einen Profils. Er kann immer noch nicht Ihre Dokumente, Ihren Schlüsselbund, Ihre anderen Profile oder den Rest Ihres Computers sehen. Und wenn Sie jemals vermuten, dass dieses Profil etwas aufgefangen hat, was es nicht sollte, können Sie die gesamte VM auf ihren letzten sauberen Snapshot zurückrollen, was ungefähr so lange dauert wie ein Browser-Neustart.

Der allgemeine Punkt

Es wäre einfach, das Obige als „Bromure besiegt zufällig genau diesen Service-Worker-Bug" zu lesen. Das stimmt, aber das ist nicht die interessante Aussage. Die interessante Aussage ist allgemeiner, und dieser Vorfall ist nur ein kleines Indiz dafür.

Browser-Zero-Days werden weiterhin auftauchen. Dies ist mindestens der zweite Chromium-Service-Worker-Bug in den letzten zwölf Monaten. Die großen aus den Jahren 2024 und 2025 waren V8-Type-Confusions und Mojo-Sandbox-Escapes, bezahlt zu sechsstelligen Preisen, eingesetzt von kommerziellen Spyware-Anbietern und staatsnahen Gruppen. Es gab Renderer-Kompromittierungen, bevor es Service Worker gab; es wird Renderer-Kompromittierungen noch lange geben, nachdem dieser spezielle Bug gepatcht ist. Die Ökonomie der Suche nach neuen — vor allem mit Mythos-Klasse-KI-Auditoren, die nun auf beiden Seiten des Offenlegungsfensters mitwirken — bewegt sich gegen den Verteidiger, nicht in seine Richtung.

Die relevante Frage, wenn ein Zero-Day zündet, lautet nicht war der Browser fehlerfrei. War er nicht. Die relevante Frage lautet was hat der Exploit tatsächlich erreicht.

Mauer = In-Process-SandboxRenderer (V8, Blink, Codecs…)SANDBOX (Mojo IPC, seccomp)gleiche Adressraum-Genealogie wie der BugBrowser-Prozess (Broker)IHR HOSTDokumente · Schlüsselbund · SSH-Schlüssel · ~/.awsiCloud · Webcam · Mikrofon · lokales Netzwerk— was ein Sandbox-Escape erreicht —Mauer = separate VMRenderer (V8, Blink, Codecs…)Browser-Prozess (Broker) — im GastHYPERVISOR-GRENZEseparater Kernel, separater Adressraum,keine gemeinsamen Bytes mit dem BugIHR HOSTDokumente, Schlüsselbund, SSH-Schlüssel, ~/.aws —nichts davon ist für den Gast sichtbar.— was ein Sandbox-Escape erreicht: mehr Gast —
Zwei Möglichkeiten, wie ein Angreifer seine Reichweite nach dem Zünden eines Browser-Bugs ausweiten kann. Bei einem traditionellen Browser ist die In-Process-Sandbox die Mauer zwischen Renderer-Code und Host; wenn jemand einen Speicherfehler in V8 oder einem Parser findet, ist diese Mauer es, die bricht. Bei Bromure ist die Mauer eine separate VM, die keinen Adressraum mit dem Browser teilt, keine Web-Bytes parst und nicht bricht, wenn ein Renderer bricht.

Ein Chromium-Sandbox-Escape — der kanonische „Browser-Zero-Day", über den Sie alle paar Monate in den letzten zehn Jahren gelesen haben — ist eine Kette, die einen Speicherfehler in irgendeinem Teil des Renderers (V8, Skia, WebP, Dawn, libxml2) nimmt und ihn nutzt, um den Broker-Prozess des Browsers davon zu überzeugen, etwas zu tun, was der Renderer eigentlich nicht tun können sollte. Diese Bugs werden zu sechsstelligen Preisen bezahlt, weil sie die Mauer überschreiten, deren Wartung den Großteil der Zeit der Chromium-Ingenieure beansprucht: die In-Process-Sandbox.

Diese Mauer ist ein bemerkenswertes Stück Ingenieurskunst. Sie ist aber auch, genealogisch betrachtet, aus derselben Art von Material gefertigt wie der Bug, der sie überwunden hat — C++, gemeinsame Adressräume, IPC-Primitive wie Mojo. Wenn ein neuer Speicherfehler in V8 oder in einem der hundert mit Chromium gebündelten Parser auftaucht, ist es die Art von Sache, die mit genug Aufwand die Sandbox aufhebeln kann.

Eine VM ist eine andere Art von Mauer. Der Browser, der darin läuft, hat keine virtuelle Speicheradresse, die auf den Host-Kernel abbildet; der Host-Kernel parst nicht die Seite, die der Browser parst; der Virtualisierungs-Stack ist eine winzige Oberfläche im Vergleich zu einem Browser, und was er parst (vCPU-Registerzustände, Paravirt-Hypercalls, virtio-Buffer-Deskriptoren), sind keine adversariellen Bytes, die von einer Webseite arrangiert wurden. Bugs an dieser Grenze existieren. Sie sind in einer anderen Schwierigkeitsliga, mehrere Größenordnungen seltener, und wenn sie auftauchen, werden sie meist vom Hypervisor-Anbieter mit einer CVE angekündigt.

Was sich für den Nutzer ändert

Im konkreten Fall des letzte Woche veröffentlichten Service-Worker-Bugs muss ein Bromure-Nutzer nicht auf einen Patch warten. Der Bug existiert auch in seinem Browser — Bromure liefert Chromium upstream aus — aber das Verhalten, das der Bug ermöglicht, ist das Verhalten, das Bromures Architektur bereits unterbindet. Ein Worker, der „für immer lebt", lebt nur so lange wie die Gast-VM, in der er registriert wurde, was höchstens so lange ist wie das Profil, das Sie pflegen, und mindestens so lange, wie der Tab geöffnet ist.

Im allgemeineren Fall „ein Browser-Zero-Day wird irgendwann im nächsten Monat auftauchen" erhält ein Bromure-Nutzer ein anderes Ergebnis. Der Exploit zündet im Worst Case gegen den Inhalt des Gasts: die Browser-Sitzung, die Cookies für die Seiten, die innerhalb dieses Profils gerade angemeldet sind, alles, was der Nutzer in diesen Browser getippt hat. Das ist ein realer Verlust, und wir versuchen nicht, ihn zu verbergen. Was nicht verloren geht, ist der Host: keine SSH-Schlüssel, kein ~/.aws, kein Schlüsselbund, keine Dokumente, kein Quellbaum, kein LLM-Agenten-Workspace.

Dieser Handel — die Browser-Sitzung kann kompromittiert werden, der Host nicht, und die Sitzung selbst ist kurz — ist der Handel, der weiterhin Sinn ergibt, je mehr neue Browser-Bugs auftauchen.

Was wir nicht behaupten

Zwei Vorbehalte, offen ausgesprochen:

Kurzlebige VMs patchen Chromium nicht

Der Service-Worker-Bug ist ein Chromium-Bug. Die richtigen Leute, um ihn zu beheben, sind die Chromium-Ingenieure, und das sollten sie auch. Bromures Architektur verändert die Kosten dafür, dass der Bug noch nicht behoben ist; sie ist kein Ersatz für die Behebung. Wir melden Dinge upstream, wenn wir welche finden, und lesen dieselben Advisories wie alle anderen auch.

Ein VM-Escape ist eine reale Kategorie

Ein Bug im Hypervisor selbst — Apples Virtualization-Framework oder einer der kleineren Oberflächen drumherum — würde es einem Angreifer grundsätzlich erlauben, den Host zu erreichen. Diese Bugs existieren. Sie sind aber auch mehrere Größenordnungen seltener als Browser-Speicherfehler, und die Oberfläche ist drastisch kleiner. Bromure macht die Anfälligkeit des Hosts gegenüber einer Renderer-Kompromittierung von dieser Bug-Klasse abhängig, statt von der Klasse, die alle paar Wochen ausgeliefert wird.

Die Schlagzeile, die Sie nächsten Monat lesen werden

Es wird einen weiteren Chromium-Service-Worker-Bug geben. Es wird eine weitere V8-Type-Confusion geben. Es wird einen weiteren libwebp-Heap-Overflow geben. Es wird einen weiteren Zero-Day geben, den ein extrem gut ausgestatteter Gegner schon extrem lange gegen extrem spezifische Personen einsetzt und der an einem Dienstagmorgen mit einer Notfall-Patch-Advisory öffentlich wird.

Die nützliche Frage am Morgen eines solchen Vorfalls ist nicht, ob Sie Ihren Browser bereits neu gestartet haben. Die nützliche Frage ist, was tatsächlich in der Box war, in der der Bug gelandet ist. Für die meisten Nutzer ist diese Box heute dieselbe Box, die ihre Dateien, ihren Schlüsselbund und ihre gespeicherten Logins enthält. Für einen Bromure-Nutzer ist die Box eine virtuelle Gast-Maschine, deren Worst-Case-Verlust das Fenster ist, das er ohnehin gerade schließen wollte.

Persistenz benötigt etwas, worauf sie bestehen kann. Machen Sie dieses Etwas kurzlebig, und eine ganze Klasse von Angriffen hört auf, eine Klasse von Angriffen zu sein.