DEV Community

TECHDEV
TECHDEV

Posted on Originally published at github.com

A trojanized Claude Code extension reached thousands of users in 11 hours. I built a verify-before-install gate for agent extensions.

On 29/10/2026, a trojanized "Claude Code" extension sat on Cursor's marketplace for 11 hours and reached roughly 5,000 users. The payload appended an SSH key to ~/.ssh/authorized_keys, opened a reverse tunnel, and persisted on the machine. And the worst part: it did not even need typosquatting. It served wrong bytes under the right identifier (Anthropic.claude-code 2.1.312/2.1.313) — on one distribution path only. A verified publisher badge would have passed it. Identity is not safety.

I built extverify — verify-before-install for agent extensions. One command, one verdict (ALLOW, DENY, or REVIEW) before the extension lands in your editor. Local, deterministic, zero runtime dependencies.

$ extverify verify anthr0pic.claude-code@2.1.313   # recorded 29/10-shaped fixture

DENY  anthr0pic.claude-code@2.1.313
  [high]   publisher-name-squat: publisher "anthr0pic" within edit distance 2 of known publisher "anthropic"
  [medium] publisher-too-new: publisher first published 6.4 days ago (< 30d)
  [low]    publisher-unverified: no verified domain badge
  [high]   download-velocity-anomaly: 778 installs/day over 6.4d publisher age
  [medium] installs-no-ratings: 5000 installs with 0 ratings
  [medium] runs-on-startup: activationEvents includes "*" (code runs at every startup)
  [medium] bundled-binary: vsix ships executable: extension/bin/svc-telemetry
  [low]    single-registry: version not found on Open VSX — cross-registry hash comparison unavailable
Enter fullscreen mode Exit fullscreen mode

Against a well-known extension, the verdict is different — and honestly so:

$ extverify verify esbenp.prettier-vscode   # live, real extension

REVIEW  esbenp.prettier-vscode@12.4.0
  [medium] runs-on-startup: activationEvents includes "onStartupFinished"
  [medium] bundled-binary: vsix ships executable: extension/node_modules/prettier/bin/prettier.cjs
  [medium] cross-registry-hash-mismatch: version 12.4.0 has different sha256
           on VS Marketplace vs Open VSX — registries disagree, verify out-of-band before installing
Enter fullscreen mode Exit fullscreen mode

REVIEW means "here are the signals, you decide." There is also extverify pin <publisher.name@version> — trust a specific version once; version-repackaged fires DENY if the bytes change under that same version later.

Demo: DENY a recorded 29/10-shaped listing, REVIEW a real extension

Where rivals beat us

  • I cannot query the Cursor mirror. There is no public API for it. Against the exact 29/10 attack shape — correct identifier, wrong bytes, served on one path — listing-only checks produce REVIEW, not a confident DENY. A hard DENY needs the typosquat/velocity shape or your own local pin. If someone tells you they catch everything pre-install, ask which distribution paths they actually query.
  • mcp-audit audits extensions post-install. That is a different trade-off: it can run deeper dynamic checks extverify never attempts, at the cost of letting the code touch your machine first.
  • Socket is SaaS with real dependency-graph analysis — deeper than listing signals, but it requires an account and trusting a vendor with your manifest. extverify runs on your machine, no account, no network dependency at verdict time.
  • Registry takedowns are post-hoc by design: the 29/10 payload shipped for 11 hours before anyone reacted. Pre-install gates and post-install audits are complements, not substitutes.

Try it

git clone https://github.com/techdevfun/extverify && cd extverify
npm install && npm run build
extverify verify <publisher.name>
Enter fullscreen mode Exit fullscreen mode

MIT, zero runtime dependencies. The checks are all in the README with their severities and rationale. If you find a listing shape it misjudges, open an issue with the listing — that is the fastest way to make the next incident shorter than 11 hours.

Top comments (0)