The service worker that will not die, and the VM that does not care
Google accidentally republished a four-year-old Chromium bug last week — a service worker that keeps running JavaScript after the browser closes, on every major Chromium browser, still unpatched. The proof-of-concept is now in the wild. The interesting question is not how it works. It is what "persistence" means on a browser whose entire underlying machine ceases to exist when you close the tab.
Persistence is not a property of code. It is a property of the place the code is allowed to live. A service worker that "never dies" has a problem when the machine it was installed on is destroyed every time you close the window.
On May 20, 2026, the issue tracker for Chromium quietly removed access restrictions on a bug that had been sitting in restricted status since 2022. Within hours, the bug — together with a working proof-of-concept — was being mirrored, archived, and written up around the web. Google moved to close the issue again. It was too late; the page was already in the Wayback Machine, and BleepingComputer's writeup went live the next day.
The bug is real, the proof-of-concept works, and four years after its initial report it is still not patched in Chrome Dev 150 or Edge 148. It affects every Chromium-derived browser: Chrome, Edge, Brave, Opera, Vivaldi, Arc.
What it lets a page do is, as a sentence, mundane: register a service worker — a small piece of JavaScript that the browser agrees to keep running in the background — that does not stop running when the page closes, when the tab closes, when the browser closes, when the machine restarts. Researcher Lyra Rebane, who originally filed the bug in December 2022, summarized the worst case to BleepingComputer: on Microsoft Edge the download menu does not even appear, so the result is "completely silent JS RCE that keeps running even after you close the browser."
The technical detail of why the bug exists matters less than the class of attack it enables. It is a persistence primitive. A page you visited once, possibly months ago, possibly an ad you do not remember seeing, is allowed to keep executing code on your computer indefinitely. Botnet enrollment, ad fraud, cryptojacking, DDoS participation, slow data exfiltration, opportunistic credential harvesting whenever you log into the same site again — all of those become trivial once you have a foothold that survives the browser quitting.
It is a good bug, in the sense that it is illuminating. It is a bad bug, in the sense that it will get used.
What a service worker actually is
The web platform has, for about a decade, allowed pages to install small JavaScript programs called service workers. They run in the background, separate from any tab, and exist so that web apps can do reasonable things — cache assets so that a site loads when you are offline, deliver push notifications, sync data when the network comes back.
A service worker is registered against an origin (say, the
combination of https, the hostname example.com, and the
default port). Once registered, the browser stores it on disk and
brings it back the next time you visit anything on that origin —
or, in the case of background features like push messages,
periodically wakes it up on its own. From the user's point of
view, the worker is invisible. From the operating system's point
of view, the worker is part of the browser, running with whatever
permissions the browser process has.
The bug Rebane reported is, broadly, that a hostile page can abuse a background download API to register a worker that the browser then refuses to terminate. Other Chromium service-worker bugs of the same family have shipped before; this is at least the second in the last twelve months. The pattern — the page plants something, the browser stores it, the browser brings it back later on its own — is the part worth holding onto. It is also the pattern that runs into a wall the moment the browser stops owning a piece of long-lived disk.
What persistence requires
Persistence — in the security sense, not the web-platform sense — is the move an attacker makes immediately after initial access. A page or a binary lands on your machine and, before doing anything else interesting, arranges for some part of itself to survive the obvious cleanup steps: closing the tab, quitting the browser, rebooting, putting the laptop to sleep on the train home. On a desktop OS, persistence has a vocabulary of its own — launch agents on macOS, scheduled tasks on Windows, systemd user units on Linux, browser extensions, autostart entries.
A service worker is, in effect, an in-browser launch agent. It is registered, stored, and brought back to life on a schedule the browser controls. It is one of the more elegant persistence primitives the web platform offers, which is part of why it keeps attracting bugs.
Crucially, every form of persistence in that list has the same
requirement, stated in three words: something must persist.
A launch agent persists because there is a filesystem on which
the agent's .plist file is written, and the agent is read back
from that filesystem at every boot. A service worker persists
because there is a browser profile on which the worker's
registration is written, and the registration is read back
whenever the browser starts. Take away the storage layer and the
"persistence" goes with it.
That sentence — take away the storage layer and the persistence goes with it — is the part of the architecture Bromure was written around.
How Bromure runs a browser
A Bromure session is not a process. It is a virtual machine. When you open a browser window, the host launches a small disposable Linux guest on Apple Silicon's hypervisor. The browser process inside that guest is what your tabs run in. The guest has its own filesystem, its own memory, its own kernel. None of those things are the host's.
There are two pieces of that architecture that matter for the service-worker bug in particular.
First, the on-disk profile that a service worker registration would normally live in is inside the guest's filesystem, not your Mac's filesystem. When the guest goes away, that filesystem goes with it. Second, the guest itself has a lifetime that the user sets — by default, a guest is tied to a profile (work, personal, banking, an LLM-coding sandbox) and is wiped when the user chooses, but for ephemeral tabs the guest is destroyed when the window is closed. Even in profile mode, the guest is one disk-volume snapshot the user can roll back at any time.
In the disposable case, the "never dies" worker has nowhere to not-die from. The on-disk row it would have been re-read from at the next browser launch was inside a virtual machine that no longer exists. The JavaScript that "kept running after the browser closed" only kept running because there was something for it to keep running on. When the browser closing also closes the underlying machine, the worker stops at the same time as the browser — exactly the behavior the original spec assumed.
In the profile case — say, you keep a long-lived "social media" profile that is meant to remember you between sessions — the worker survives the way it always has, scoped to that one profile's VM. It still cannot see your Documents, your keychain, your other profiles, or the rest of your computer. And if you ever suspect that profile has picked up something it should not, you can roll the whole VM back to its last clean snapshot, which takes about as long as relaunching a browser.
The general point
It would be easy to read the above as "Bromure happens to defeat this specific service-worker bug." That is true, but it is not the interesting claim. The interesting claim is more general, and this incident is one small piece of evidence for it.
Browser zero-days will keep landing. This is at least the second Chromium service-worker bug in the last twelve months. The big ones from 2024 and 2025 were V8 type confusions and Mojo sandbox escapes, paid for at six-figure prices, used by commercial spyware vendors and state-aligned groups. There were renderer compromises before service workers existed; there will be renderer compromises long after this particular bug is patched. The economics of finding new ones — especially with Mythos-class AI auditors now in the loop on both sides of the disclosure window — are moving against the defender, not towards them.
The relevant question, when a zero-day fires, is not was the browser flawless. It was not. The relevant question is what did the exploit actually reach.
A Chromium sandbox escape — the canonical "browser zero-day" you have read about every few months for the last decade — is a chain that takes a memory bug in some piece of the renderer (V8, Skia, WebP, Dawn, libxml2) and uses it to convince the browser's broker process to do something the renderer was not supposed to be able to do. Those bugs are paid for at six figures because they cross the wall the Chromium engineers spend most of their time maintaining: the in-process sandbox.
That wall is a remarkable piece of engineering. It is also, genealogically, made of the same kind of stuff as the bug that crossed it — C++, shared address spaces, IPC primitives like Mojo. When a new memory bug shows up in V8 or in one of the hundred parsers bundled with Chromium, it is the kind of thing that can, given enough work, lever the sandbox open.
A VM is a different kind of wall. The browser running inside it
does not have a virtual memory address that maps to the host
kernel; the host kernel does not parse the page the browser is
parsing; the virtualization stack is a tiny surface compared to a
browser, and what it parses (vCPU register states, paravirt
hypercalls, virtio buffer descriptors) is not adversarial bytes
arranged by a web page. Bugs at that boundary do exist. They are
in a different league of difficulty, are several orders of
magnitude rarer, and when they appear they are usually announced
by the hypervisor vendor with a CVE.
What this changes for the user
In the specific case of the service-worker bug exposed last week, a Bromure user does not need to wait for a patch. The bug exists in their browser too — Bromure ships Chromium upstream — but the behaviour the bug enables is the behaviour Bromure's architecture already disables. A worker that "lives forever" lives only as long as the guest VM it was registered in, which is at most as long as the profile you keep, and at least as long as the tab is open.
In the more general case of "a browser zero-day will land
sometime in the next month," a Bromure user gets a different
shape of outcome. The exploit fires, in the worst case, against
the contents of the guest: the browser session, the cookies for
the sites currently logged in inside that profile, anything the
user has typed into that browser. That is a real loss and we are
not trying to hide it. What is not lost is the host: no SSH keys,
no ~/.aws, no keychain, no Documents, no source tree, no
LLM-agent workspace.
That trade — the browser session can be compromised, the host cannot, and the session itself is short — is the trade that keeps making sense as the rate of new browser bugs goes up.
What we are not claiming
Two caveats, stated openly:
Disposable VMs do not patch Chromium
The service-worker bug is a Chromium bug. The right people to fix it are the Chromium engineers, and they should. Bromure's architecture changes the cost of the bug not being fixed yet; it is not a substitute for fixing it. We file upstream when we find things, and we read the same advisories everyone else does.
A VM escape is a real category
A bug in the hypervisor itself — Apple's Virtualization framework, or one of the smaller surfaces around it — would, in principle, let an attacker reach the host. Those bugs exist. They are also several orders of magnitude rarer than browser memory bugs, and the surface is dramatically smaller. Bromure makes the host's exposure to a renderer compromise contingent on that class of bug, instead of on the class that ships every few weeks.
The headline you will read next month
There will be another Chromium service-worker bug. There will be
another V8 type confusion. There will be another libwebp heap
overflow. There will be another zero-day that an extremely
well-resourced adversary has been using against extremely
specific people for extremely long, that becomes public on a
Tuesday morning with an emergency patch advisory.
The useful question, on the morning of any of those, is not whether you have already restarted your browser. The useful question is what was actually inside the box the bug landed in. For most users, today, that box is the same box that holds their files and their keychain and their saved logins. For a Bromure user, the box is a guest virtual machine whose worst-case loss is the window they were about to close anyway.
Persistence requires something to persist on. Make that something disposable, and a whole class of attack stops being a class of attack.