ai newsSo., 18. Okt.
EilmeldungClaude Code 2.1.302 Flips Two claude -p Defaults: Permission Mode and Fork Subagents

SneakPeek: the Claude Code bug that lived in the preview, not the agent

On October 14 Noma Labs published SneakPeek , an exploit chain in Claude Code Desktop's preview pane. A malicious HTML file in a public repository could run JavaScript when Claude previewed it, read files from your home directory, and send them to an attacker's server. Noma's list of what the proof

dev.toSonntag 14:01 · 18.10.5 Min. Lesezeit
Bild: dev.to

Posted on Oct 18 • Originally published at reado.watermelon-studio.it

It's fixed: according to Noma's timeline, Anthropic shipped the fix on August 17, in Claude Desktop 1.30096.1 and later, through auto-update. If your app updates itself, you've had it for two months.

I build Reado, an IDE for reading the code your agent writes, so a bug that lives in "showing the user a file" is squarely my problem too. This post is about why this one is worth understanding even though it's closed, and what I checked in my own app after reading it.

When Claude reads or edits an HTML file, Claude Code Desktop shows it in a preview pane, so you see the result right away. Noma describes three defenses around that pane:

The gaps were in where each one applied. Files under 256KB were loaded as data: URLs, with the CSP. Files over 256KB were written to a temp file and loaded as file:// URLs, and that path never got the CSP. In Chromium a file:// page can fetch() other local files. And the request filter was only active when the pane was proxying a running dev server, not when it rendered a static file from disk.

So the attack is: pad an HTML file past 256KB, put a script in it, and wait for someone to look at it. Noma disguised it as a test coverage report, a file nobody is surprised to find large. The victim clones the repository and asks Claude to look at the coverage report. Claude reads the file, the pane renders it, the script runs.

There was no permission prompt at any point, and that's the part I keep thinking about. Claude didn't run a command or write a file. It read a file, which is the most harmless thing an agent can do. The code ran in the application's renderer, as a side effect of showing you the result.

Noma reported the bug on July 4. Anthropic's first patch blocked fetch() and XMLHttpRequest calls to file:// from the page. Noma moved the same fetch() into a Web Worker created from a blob: URL, a context the filter didn't cover, and the files came out again. They reported the bypass on July 24, the same day the patch was ready for retest. On August 3 Anthropic confirmed the first fix was incomplete and started a complete one, covering, in Noma's words, "CSP, file:// loading, and the Worker bypass". It shipped on August 17.

Noma's write-up credits Anthropic for "iterating on every bypass until achieving a comprehensive, layered fix", and the timeline backs that up. But the bypass itself is the lesson. The first patch blocked the APIs the proof of concept had used. The attacker used another one. The complete fix went after the conditions instead: the CSP, the file:// loading, and the Worker.

A second code path is a second security model. My guess is that the 256KB cutoff was a performance decision: large data: URLs are slow. Nobody decides "large files get no CSP". But a threshold quietly sent the large ones down a path with different rules. If a feature has two ways of doing the same thing, each one needs its own security review. Better still, have one way.

The permission system guards the agent, not the app around it. Most of what we do to make coding agents safe is about the agent: approve this command, deny writes outside the project, sandbox the shell. All of that was in place here and none of it was involved. Carlos, commenting on a dev.to write-up of the bug, put it well: "Here a file in the repo was the attacker and the viewer was the tool." Anything that renders what's in a repository (previews, Markdown, notebooks, images, an embedded browser) is part of the attack surface, whether or not an agent is involved.

"Review this file" is when you trust the file least. The request that triggered SneakPeek was a review: look at this coverage report. That's the moment the file has been seen by nobody you trust, so the surface showing it should be the least capable one in the app, not the most.

Reado has the same problem to solve: it exists to show you the files in a repository, most of which you didn't write. After reading Noma's post I went through every place it does that, with SneakPeek's three questions: does the file's code run, can the page read the disk, can it send anything out.

The same pass turned up two bugs in a surface I hadn't thought of as "showing files": Reado's embedded browser, the pane for previewing your dev server. It takes URLs from two places a repository can control. Design comments, which live in.reado/ like every Reado comment, carry the URL of the page they're pinned to. And agents drive the pane through a command file in the same folder. So a cloned repository could ship a comment pointing at a file: or data: page, or a command already waiting for the pane to open. Both are fixed: the pane now opens only http and https pages, checked in one place in the Rust layer that every caller goes through, and a command that was already there when the pane opened is recorded, never run. The fixes are on main and ship in the next release.

The common thread is a choice I made for other reasons: Reado is built around reading code, so its default for a file is to show the text. That's less impressive than a live preview, and after SneakPeek it's one I'm glad of.

If you use Claude Code Desktop, check that you're on Claude Desktop 1.30096.1 or later. Noma's post also lists the GitHub advisory and CVE as pending, so watch for those.

If you build a tool that shows files from a repository, a few rules follow from this bug:

Anthropic fixed this one, and kept at it until the bypass was closed too. The pattern isn't specific to them: every coding tool that shows you a file has a version of that preview pane. It's worth looking at yours before someone else does.

Quelle: dev.to (dev.to). Original öffnen