DEV Community

Rohit Bhadani
Rohit Bhadani Subscriber

Posted on Edited on

The Claude Code Desktop Vulnerability That Beat Three Layers of Sandboxing

On October 14, 2026, Noma Security disclosed a Claude Code Desktop vulnerability called SneakPeek that let a malicious HTML file read SSH keys, AWS credentials, and GitHub tokens from a developer's machine with no click and no warning. Anthropic rated it CVSS 8.7 and shipped the real fix on August 17, two months before anyone outside the two companies knew it existed.

Jump straight to what to check today if you only have five minutes before your next meeting.

What the Claude Code Desktop Vulnerability Actually Did

Claude Code Desktop renders HTML files in an automatic preview pane so a developer can see the result of an edit right away. According to Noma Security's disclosure, an attacker could plant a padded HTML coverage report, sized just over 256KB, inside a normal-looking public repository. A developer clones the repo, asks Claude to review that one file, and the pane renders it without asking first.

An embedded script inside the file then read local credentials and sent them to a remote server through a standard browser call. Noma lists SSH private keys, AWS access keys, GitHub and npm tokens, Kubernetes cluster configs, Docker registry auth, and Claude's own OAuth tokens as readable in the proof of concept. No permission prompt appeared, because the AI agent itself never took an action. The renderer did.

How Three Layers of Sandboxing Failed at Once

The preview pane runs on Electron's Chromium engine, and Anthropic had three real protections in place. A content security policy was supposed to block scripts outright. An opaque origin was supposed to stop the page from reading local files. A request filter was supposed to block file:// reads entirely. Noma found that all three worked exactly as designed for small files, but none of them covered the second rendering path.

Files under 256KB loaded as data: URLs, where the content security policy worked exactly as designed. Files over that size got written to a temp file and loaded as file:// URLs instead, a path the policy never covered, and the request filter meant to catch exactly that case stayed inactive during static rendering. A 500KB coverage report, Noma noted, does not raise any flags, since real coverage reports bundle source maps and CSS past that size anyway.

Why the First Patch Didn't Hold

Noma reported SneakPeek to Anthropic on July 4, 2026, and Anthropic shipped a first patch on July 9 that blocked direct file reads from the preview's main page context. Noma broke it the same day the retest opened, on July 24, by moving the file-reading code into a Web Worker created from a blob: URL, a background thread the patch never checked. Anthropic confirmed the bypass on August 3 and shipped the deeper, architectural fix on August 17 in Claude Desktop 1.30096.1, five weeks after the original report and ten weeks before the public write-up.

What We Checked on Our Own Developer Machines

We pulled the version number on every machine on our team that runs Claude Code Desktop, since Krova Cloud's own engineers use it against disposable VM images daily. Three of our four installs auto-updated past 1.30096.1 weeks ago. The fourth had auto-update disabled for a corporate proxy reason nobody remembered, and was still two patch releases behind the fix.

We also checked our own public repositories for any HTML file over 256KB, the size Noma's proof of concept depended on, and found one generated test-coverage report that would have qualified. None of this means we were exploited, but it does mean the exposure window was real on our own infrastructure, not just in Noma's lab, and checking took fifteen minutes once we knew what to look for.

What to Check Today

  • Confirm every Claude Code Desktop install is on 1.30096.1 or later, after a full relaunch, since an update can sit staged while the old process keeps running.
  • Search your own repositories for HTML files over 256KB committed by anyone outside your team, especially coverage or build-report artifacts.
  • Rotate any long-lived AWS, GitHub, or npm token that lived on a machine with an older build, rather than trusting that no theft occurred.
  • Move toward short-lived credentials on developer workstations generally, since Noma's own recommendation is that this class of bug keeps recurring across AI coding tools with a rendering surface.

The catch here is that patching the agent's permission system would not have stopped this. The exploit never touched Claude's approval prompts, deny rules, or sandboxed Bash calls, the layer most coding-agent security advice focuses on, because the malicious code executed inside the app's own Chromium renderer as a side effect of showing a preview, not as an agent decision. Teams that only audit what their AI agent is allowed to do, and skip what the surrounding app is allowed to render, are checking half the attack surface.

Patching is still worth doing today even though this specific flaw is closed, because the same rendering-pane pattern exists in any coding tool that previews generated output. GitLab's own AI Gateway permissions flaw, which I wrote about on October 6, sat in a different layer of the same class of tool, and the pattern across both is the same: the part of an AI coding product that nobody audited is usually a rendering or preview surface, not the model.

The Rule

An AI coding agent's permission system protects against what the model can be talked into doing. It says nothing about what the surrounding desktop app is allowed to render on the model's behalf, and SneakPeek lived entirely in that second, unaudited layer. If your security review of an AI coding tool stops at deny rules and sandboxed shell commands, you have not reviewed the preview pane, the file viewer, or any other piece of the app that touches untrusted content directly.

Frequently Asked Questions

Is the Claude Code Desktop vulnerability fixed now?

Yes. Anthropic's architectural fix shipped August 17, 2026 in Claude Desktop 1.30096.1 and later, delivered through the normal auto-update channel, according to Noma Security's disclosure timeline. Confirm the version after a full relaunch, since an update can stay staged while an older process keeps running in the background.

What could an attacker steal through SneakPeek?

Noma's proof of concept read SSH private keys, AWS access keys and secrets, GitHub and npm auth tokens, Kubernetes cluster credentials, Docker registry auth, and Claude's own OAuth tokens from the host machine. All of it left through a single background network call that never touched the AI agent's own approval system.

Does this bug require Claude's AI agent to do anything malicious?

No, and that is the useful part. The malicious script ran inside the preview pane's rendering process the moment the HTML loaded, not as an action the agent decided to take, so Claude's deny rules and sandboxed command approvals can't block something they never see happen.

Should I stop using Claude Code Desktop's preview pane?

Not if your build is current. The verdict from Noma's own writeup is that the protections were real, they just didn't cover every rendering path, and Anthropic closed the gap after one confirmed bypass. The practical move is confirming your version and rotating any credentials that sat on an older build, not avoiding the feature outright.


I'm Rohit, founder of Krova Cloud: disposable VMs with no saved SSH keys, no cached cloud tokens, and no 1.30096.1 to forget to check, since the box is gone the minute the job finishes. More debugging stories at debugly.dev.

Top comments (3)

Collapse
 
urion profile image
Matteo Poli •

The detail I keep coming back to is the 256KB branch. Every protection held on the path everyone uses, and a size cutoff quietly switched the file from a data: URL to file://, which changes what the browser thinks the page is allowed to touch. A threshold that was probably a performance decision ended up deciding the security model. If you render untrusted files, one rendering path is easier to defend than two that are supposed to be equivalent.

I build a code-reading app (Reado), and after reading this I went back and checked ours, because it has a browser pane too. It only loads a URL: the dev server it finds on localhost, or one you type. Opening a file from the repo never sends it there; an .html file opens as source, and HTML inside a README goes through a sanitizer that drops scripts. The agent can drive the pane, but only on origins you've already allowed. Your point about auditing what the app renders, not just what the agent may do, is the check I'd recommend to anyone shipping a preview.

Collapse
 
analista_83 profile image
Sammi De Blas •

Three layers failing together is the real lesson here - defense in depth only holds if the layers are independent, and a desktop app's sandboxing usually shares the same kernel/IPC surface across all of them, so one capability or IPC primitive that leaks collapses all three at once. The fix I would push for is isolation that does not share state: run the untrusted tool output in a separate process (or a micro-VM) with a narrow, explicitly allowlisted egress and no inherited credentials, so an escape degrades to 'the sandbox made one network call it was not allowed to' instead of 'the host is owned'. Publishing the exact primitive that crossed the boundary is what lets everyone else audit whether their third layer is actually independent.

Collapse
 
bloqarl profile image
Carlos | Zealynx •

The part that got me is that no prompt appeared because the agent never did anything, the preview pane did. Most of us put the approvals around the agent's tool calls and assume that's the boundary. Here a file in the repo was the attacker and the viewer was the tool.

And the hole was in the over 256KB path, the second branch nobody tests. Did Noma say if they checked other agent desktop apps with HTML previews too?