Vulnerabilities
SneakPeek: Claude Code Desktop preview leaked dev secrets
A padded HTML coverage report could make Claude Code Desktop's preview pane read SSH keys and cloud tokens. Fixed in 1.30096.1. Update, check, rotate.
On October 14, Noma Labs published SneakPeek, a flaw in the preview pane of Claude Code Desktop, the coding agent inside Anthropic's Claude Desktop app. A malicious HTML file in a cloned repository could run JavaScript when the pane rendered it, read files from the developer's home directory and send them to an attacker's server. Anthropic scored it 8.7 (High) under CVSS 4.0, the Common Vulnerability Scoring System, and treated the impact as equivalent to code execution on the host.
The fix is already out. Anthropic shipped it on August 17 in Claude Desktop 1.30096.1 and later, through auto-update. Teams that use Claude Code Desktop on real projects should still confirm every machine is on that build, and ask whether anyone previewed HTML from an untrusted repository before it landed. No CVE ID or GitHub Security Advisory had been published when Noma went public. Noma's Eli Ainhorn told CSO Online that Anthropic is preparing an advisory and has requested a CVE.
How it works
When Claude reads or edits an HTML file, Claude Code Desktop shows it in a preview pane built on Electron's Chromium renderer. Noma found three protections around that pane. Small files were loaded as base64 data: URLs carrying a Content Security Policy (CSP, a browser rule set) of script-src 'none', which blocks every script. A data: URL also gives the page an opaque origin, so it cannot request local files. And a request filter blocked file:// reads when the preview was proxying a local dev server.
Each protection had a gap, and they lined up. Files of 256KB or more were written to a temp file and loaded as a file:// URL instead, so they never got the CSP and their scripts ran. A file:// page in Chromium shares an origin with the local filesystem, so fetch() could read other files on disk. The request filter only applied to the dev server path, not to a static HTML file opened from disk, which is exactly how a test coverage report is viewed.
The developer saw no prompt. Claude's permission system governs what the agent does, and here the agent did nothing unusual: it opened a file it was asked to review. The script ran inside the renderer, which is also why, as Sysdig's Crystal Morin told CSO Online, agent-level logs would not be expected to show it.
What a malicious repository looks like
Noma's demonstration repository looked like any small project: source files, tests and a coverage report. The report was padded past 256KB, with the JavaScript payload buried inside. Real coverage reports are often that large, so the size raises no suspicion.
The victim clones the repository and asks Claude to review or fix the report. The pane renders it, and the script works out the home directory from the temp file's path. It then reads SSH private keys, AWS access keys, npm and GitHub tokens, Kubernetes and Docker registry credentials, Git identity and Claude's own OAuth tokens. It ships them with navigator.sendBeacon(), a background HTTP POST that the app's missing outbound CSP did not stop. Noma also captured the victim's real IP address through WebRTC.
The patch that was bypassed
Noma reported the flaw on July 4 and Anthropic triaged it on July 9. Anthropic's first patch, deployed on July 24, blocked fetch() and XMLHttpRequest calls to file:// paths from the main page. Noma bypassed it the same day by moving the fetch() into a Web Worker, a background script thread, created from a blob: URL. The Worker was outside the patched context, read the same files and passed them back to the page. Anthropic confirmed the fix was incomplete on August 3 and made deeper architectural changes for the August 17 release.
No source reports SneakPeek being used outside Noma's research. Noma told CSO Online that Anthropic worked with it on the disclosure and has fully resolved the issue.
What to do
1. Confirm the fixed build
Check the version in Claude Desktop's About window on every developer machine. It must be 1.30096.1 or later. Relaunch the app after an update, since a downloaded update may not be running yet. Updating the claude command-line tool does not update the Desktop app. Installs pinned by MDM (mobile device management) or a software catalogue do not auto-update, so check the version those tools deploy.
2. Look for suspect files
In repositories that were reviewed with Claude Code Desktop before the update, list large HTML files:
find . -name '*.html' -size +256k
A hit is a reason to open the file in a text editor and look for script blocks, sendBeacon or fetch('file:// calls. Most large HTML files will be ordinary coverage output.
3. Check whether secrets were used
If a suspect file turns up, or you cannot rule one out, review where the exposed credentials work:
- AWS. Run
aws iam get-access-key-last-used --access-key-id <id>for each key that sat in~/.aws/credentials, thenaws cloudtrail lookup-events --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=<id>in each Region. Event history only covers 90 days, which no longer reaches back to early July, so query your CloudTrail trail in S3 or CloudTrail Lake for older activity. - GitHub. Open Settings, then Security log under Archives, and filter on
personal_access_tokenandpublic_keyevents. Org owners should check the organisation audit log for clones and token use from unfamiliar addresses. - npm. Run
npm token listand revoke any token you do not recognise, or every token, withnpm token revoke <id>. Check recent versions of packages you publish for releases you did not make. - Review Kubernetes API server audit logs for the users in each kubeconfig, and Docker registry logs for pushes.
4. Rotate what sat on disk
If logs do not reach back far enough to clear a credential, rotate it. Replace SSH keys and remove the old public keys from GitHub and servers, deactivate and reissue AWS access keys, and revoke npm and GitHub tokens. Kubeconfig credentials and Docker registry logins belong on the same list, as does the Claude account signed in on that machine.
5. Treat cloned repositories as untrusted input
Like Plugin4Shell in September, SneakPeek turned a routine action on someone else's repository into access to the developer's machine. Open unfamiliar repositories in a disposable container or VM with no home directory credentials mounted. Move developers to short-lived credentials (AWS IAM Identity Center sessions, fine-grained GitHub tokens with expiry, granular npm tokens), as Ainhorn advised. Acalvio's Ram Varadarajan suggested decoy credentials in the paths agents can reach, so any read raises an alert.
The wider lesson
A size threshold and a filter that only covered one code path sat between a public repository and a developer's keys. Agent permission prompts protect against what the model decides to do. They do not cover the editor, renderer or extension that displays the model's work, and those components need the same review as any browser that opens untrusted content.
Our red team and code review work tests developer tooling and the paths from a repository to a workstation's secrets, and our AI-native systems team helps set up coding agents with scoped credentials and isolated workspaces. Open the chat and Yaali, our AI agent, will pass your question to the engineer who would do the work.
Sources: Noma Labs, CSO Online, Hackread, Developers Digest, Let's Data Science, Dark Reading, Cybernews, AWS CloudTrail lookup-events, GitHub security log, npm token.