RC RANDOM CHAOS

A single file freezes your Mac

A WebGPU shader with an infinite loop locks up an M-series Mac until a watchdog forces a reboot. One click triggers it, and Apple declines to fix it.

· 4 min read
A single file freezes your Mac

A WebGPU compute shader with a deliberately broken loop can lock up the desktop on an M-series Mac badly enough that a watchdog forces a kernel panic and reboots the machine. The only thing the victim does is click a link. Auberon López, who found the bug and named it the deathray, reproduced it on macOS Tahoe across Chrome, Firefox, and Safari. It does not reproduce on other operating systems.

The code is small, mostly HTML scaffolding around two short shaders. The interesting part is a compute shader whose loop never advances:

@compute @workgroup_size(1) fn compute() {
  for(var i = 0u; i < 1;) {
    data[i+1] = data[i];
  }
}

There is no i++, so the loop spins forever, copying the same vector back into a storage buffer. A vertex shader reads from that same buffer. Because the compute shader never returns, the vertex shader can’t proceed and GPU work backs up behind it.

That backlog doesn’t stay inside the browser. macOS’s WindowServer needs the GPU too, and it goes unresponsive along with the shader. The symptoms vary: sometimes the mouse still moves, sometimes a beachball, sometimes magenta garbage across part of the screen. López doesn’t know what decides which.

The rest of the machine keeps running. You can SSH in while the display is dead. What ends the session is a watchdog on WindowServer: once it has been unresponsive long enough, the watchdog fires a kernel panic and the Mac restarts. Holding the power button does the same thing sooner. Hardware seems to change the severity; testers on Hacker News reported that Max-tier M-series chips are less likely to freeze completely and Intel Macs look less susceptible.

Apple has been here before. In 2023 Ron Masas of Imperva built ShadyShader, a WebGL shader that hogged the GPU using enormous nested loops that were technically finite. Apple assigned CVE-2023-40441 at 6.5 (medium) and shipped better input validation to catch runaway loops. The deathray’s loop is trivially identifiable as infinite, which suggests WebGPU never got that validation. Chasing specific loop shapes was always a weak defence, since no validator can decide whether an arbitrary shader terminates. The fix that holds is pre-emption of unresponsive GPU work, which every other OS López tested already does.

Part of why this is hard on Apple Silicon is structural. The kernel can’t pre-empt the GPU directly. GPU scheduling runs on a coprocessor, the ASC, and the pre-emption logic lives in ASC firmware that the kernel talks to rather than drives. (Asahi Lina’s writeup on the M-series GPU covers the architecture.)

The disclosure went in two directions. López reported the bug to Apple Security on 27 July 2026. Apple reproduced it quickly, said it intended to fix it, and gave a timeline it marked confidential. On 26 August Apple reversed course: it did “not see any security implications” in the report, said the report did not “result in a change in [Apple’s] products,” and routed it to another team for “potential enhancement considerations.” Its reasoning was that “the result is either a crash, hang, or recoverable data loss which we do not consider to be a security issue.” That reading is hard to square with the 6.5 Apple handed ShadyShader.

The security engineers López spoke to mostly agree with Apple on the technical point. Non-security people were surprised, and López leans toward their view: people trust that clicking a link can, at worst, bog down a tab, and a drive-by page that reboots the whole machine breaks that assumption in a way a crash log doesn’t capture.

There is no patch, and the “enhancement considerations” filing suggests one isn’t close. WebGPU ships in Chrome, Firefox, and Safari on macOS, so any page you open can run this shader. If you manage Macs where a surprise reboot is costly, disabling WebGPU in the browser is the only control available today. The display freeze doesn’t take out networking, so you can still SSH in before the watchdog fires if you need to pull work off a stuck machine. And if your browser restores tabs on launch, a reboot can drop you straight back onto the page that froze you, so clear the session before you reopen it.

Share

Keep Reading

Latest on the Wire

Full wire →

New signal daily · RSS

Stay in the loop

New writing delivered when it's ready. No schedule, no spam.