wormcheck $5/mo · subscribe

for developers who let Claude Code, Cursor or Codex run installs

Is the npm worm in your Claude settings?

Recent npm and PyPI worms plant themselves in Claude Code hooks, VS Code tasks and Python startup files, where deleting node_modules doesn't reach. Wormcheck checks those places and your lockfiles, on your machine. Check in one command.

$5/month30-day money-backmacOS + LinuxNode 18+

where it hides
  1. 01~/.claude/settings.jsonHooks Claude Code runs for you, including on session start.
  2. 02.vscode/tasks.jsonA task set to run on folder open, every time you open the project.
  3. 03site-packages/*.pthPython runs import lines in these files every time it starts.
deleting node_modules removes none of these

pain · in their words

Wipe the repo, reinstall, and the question is still there: how do I check?

r/ClaudeAI · reply in a 1,438-upvote thread

Still compromised even after the wipe.

“The machine is still compromised even after the wipe. the persistence lives in ~/.claude/settings.json, .vscode/tasks.json and the python startup hook”
read the thread ↗

r/node · post

npm audit, Snyk, Dependabot all passed them clean.

“Every major npm supply chain attack last year had no CVE... npm audit, Snyk, Dependabot all passed them clean.”
read the thread ↗

r/programming · 377-upvote thread title

A near daily occurrence.

“Why have supply chain attacks become a near daily occurrence?”
read the thread ↗

A scanner that looks for known vulnerabilities has nothing to report on a malicious package with no CVE, and it never opens your agent's config. Each new wave also moves to new files and new strings. Wormcheck tracks those, wave by wave.

how it works · three commands

One command checks the places the worm hides.

wormcheck scan

Check this machine and this project

Reads the persistence points above and the lockfiles in the current folder tree, then compares them against the current wave indicators and OSV's malicious-package advisories.

INFECTED means a match on a published indicator. REVIEW means something legitimate but worth a look, such as any session-start hook. It never calls a machine infected on a guess.

wormcheck update

Pull the new wave's indicators

When a new wave is published, its file paths, strings and package versions go into the feed the same day. Every indicator links to the vendor or advisory it came from, so you can check our work.

The scan header shows the rules version and date, and warns when your rules are more than 14 days old.

wormcheck harden

Tighten how your agent installs packages

Adds a Claude Code install gate: before the agent runs an npm, pnpm, yarn, bun, pip or uv install, it blocks a package version published in the last 7 days, a version on a known-compromised list, or a near-lookalike name; if the registry can't be reached it lets the install through. It also sets ignore-scripts in ~/.npmrc if you haven't, and pnpm's minimum release age.

It shows the diff and asks before writing, backs up every file it touches, and leaves your existing hooks alone. --remove takes out exactly what it added. The gate is a speed bump, not a sandbox.

wormcheck scan · seeded test machine
wormcheck 0.1.1 · rules 2026.11.15-2 (bundled, updated 2026-11-15, 0 days old) · 7 waves
scanned ~/code/my-app · 3 agent/editor configs · 0 .pth files · 1 lockfile (2 packages)
OSV: 2 packages checked against malicious-package (MAL-) advisories

INFECTED (3)
  ./.claude/settings.json:9
    SessionStart hook matches a Mini Shai-Hulud (TeamPCP) indicator
    runs: node .vscode/setup.mjs
    indicator: node .vscode/setup.mjs · Mini Shai-Hulud (TeamPCP)
    SessionStart hook the worm commits into a project so it runs on every Claude Code session.
    source: https://www.stepsecurity.io/blog/a-mini-shai-hulud-has-appeared
    source: https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem
  ./.vscode/tasks.json:7
    task "Environment Setup" matches a Mini Shai-Hulud (TeamPCP) indicator (runs on folder open)
    runs: node .claude/setup.mjs
    indicator: node .claude/setup.mjs · Mini Shai-Hulud (TeamPCP)
    Folder-open task ("Environment Setup") that reruns the loader whenever the folder is opened.
    source: https://www.stepsecurity.io/blog/a-mini-shai-hulud-has-appeared
  ./package-lock.json:10
    lockfile pins compromised npm package @tanstack/router-core@1.169.5
    indicator: @tanstack/router-core@1.169.5 · Mini Shai-Hulud (TeamPCP)
    source: https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem

REVIEW (3)  legitimate mechanisms that malware also uses; not evidence of infection
  ./.claude/router_runtime.js
    a file at a path the Mini Shai-Hulud (TeamPCP) wave used; check whether you created it
    Bun payload dropped into .claude/ for persistence (TanStack wave). The name alone is not proof (no published hash or content to compare). Source: https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem
  ~/.claude/settings.json:10
    PreToolUse hook runs a command (matcher "Bash")
    runs: ~/bin/guard.sh
    PreToolUse hooks run automatically before tool calls. Keep it if you added it; delete it if you do not recognise it.
  ~/.local/bin/gh-token-monitor.sh
    a file at a path the Mini Shai-Hulud (TeamPCP) wave used; check whether you created it
    gh-token-monitor script. The name alone is not proof (no published hash or content to compare). Source: https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem

Result: INFECTED. 3 known indicators matched.

What to do now (in this order)
  1. Stop the spread: close editors and agent sessions on this machine. Do not run npm/pnpm/
     yarn/bun install or publish from it until step 6.
  2. From a different, clean device, rotate:
     - npm tokens: npmjs.com > Access Tokens > delete all; re-create later with 2FA.
       Check your packages for versions you did not publish.
     - GitHub: revoke personal access tokens (Settings > Developer settings), OAuth apps
       and SSH keys (Settings > SSH and GPG keys); sign out other sessions. Look for
       repos and workflow files you did not create.
     - Cloud keys: AWS access keys, GCP service-account keys, Azure secrets, and any
       credential in ~/.aws, ~/.config/gcloud, ~/.azure on this machine.
     - Every secret in .env files on this machine (API keys, database URLs, Stripe
       keys), plus CI secrets those repos can reach.
  3. Remove the persistence entries listed above: delete the hook / task / .pth line /
     file at each path. Keep a copy of each first if you want to report it.
  4. Remove the compromised package versions from lockfiles and node_modules; reinstall
     from a clean lockfile with scripts disabled (npm ci --ignore-scripts).
  5. Run `wormcheck scan` again until it reports no INFECTED findings.
  6. Then run `wormcheck harden` so the next install goes through the gate.
  Rotation matters more than cleanup: these worms steal credentials when they run, so
  treat every credential this machine could read as already copied.
Unedited output from a test machine we infected on purpose with published indicators. Exit code 0 = clean, 1 = indicators found, 2 = error.

What you get

  • A local CLI, wormcheck, delivered as a private download after checkout. It is not on public npm.
  • Checks of ~/.claude/settings.json hooks, .vscode/tasks.json tasks and Python .pth startup files, plus your lockfiles: npm, pnpm, yarn, bun, poetry, uv, Pipfile and requirements.txt.
  • Same-day indicator updates for each new wave, fetched with your licence key.
  • macOS and Linux, Node 18 or newer, no dependencies.

What it is not

  • Not a replacement for Dependabot or Socket on your repos. Keep those. Wormcheck looks at the machine they don't look at.
  • Not a guarantee. It finds what matches published indicators and OSV advisories. A variant nobody has published yet will not match.
  • No email alerts, sync or team features. Those don't exist yet, so we don't sell them.
  • Not tested on Windows.

// what leaves your machineYour files never leave your machine. To check lockfiles, wormcheck scan sends package names and versions to OSV's public API (api.osv.dev). Run wormcheck scan --offline to skip that call and use only the rules on disk. If you run wormcheck harden, the install gate it adds sends the names of packages your agent installs to registry.npmjs.org or pypi.org to check when that version was published.

offer

Wormcheck, $5 a month.

There is no free tier and no trial. The scan output above is exactly what you get. The guarantee covers the rest.

After checkout you get a licence key and a download link on the next page. Then four commands: install, activate, update, scan.

$5 / month

billed monthly by Stripe · cancel any time from your billing page

  • wormcheck scan: agent persistence points and lockfiles, checked locally
  • wormcheck update: same-day indicators for each new wave
  • wormcheck harden: agent install hardening, diff shown first
  • Private download and a licence key, right after checkout

30-day money-back guarantee. If it isn't for you, email team@lazarusoperations.com within 30 days of paying and we refund you in full. If you cancel, the CLI keeps the last rules it fetched and stops updating.

questions

The objections from the threads.

Dependabot and Socket are free. Why pay for this?

Keep using them. Dependabot and Socket's GitHub app watch the dependencies in your repos. The worm's persistence sits on your machine: a hook in ~/.claude/settings.json, a task in .vscode/tasks.json, a Python .pth file. None of those is a dependency or shows up in a pull request, so a repo scanner has nothing to look at.

If what you want is install-time blocking, one r/devops commenter adopted Aikido's free Safe Chain after an npm worm hit them. Wormcheck answers a different question: is anything already on this machine?

Can't I just grep for it?

You can, if you know every file location and every string for every wave, and you redo that each time a new wave changes both. That list is what the subscription keeps current. Every indicator links to its source advisory, so you can read exactly what it matches.

Why a subscription and not a one-time tool?

Because the indicators change with each wave. A scan with last month's rules cannot see this month's files and strings. The $5 pays for adding each new wave to the feed the same day it is published. If you cancel, the CLI keeps the last rules it fetched and stops updating.

What leaves my machine?

Your files never leave it. wormcheck scan sends package names and versions from your lockfiles to OSV's public API to check for malicious-package advisories. --offline skips that call. wormcheck update sends your licence key to fetch the rules. If you run wormcheck harden, the install gate it adds sends the names of packages your agent installs to registry.npmjs.org or pypi.org to check when that version was published.

What if it isn't for me?

Email team@lazarusoperations.com within 30 days of paying and we refund you in full. No form. To stop paying, cancel any time from your billing page: the Manage subscription link on the page you see after checkout.

Does it catch everything?

No, and nothing honest can promise that. It reports matches on published indicators and OSV's malicious-package advisories, and flags legitimate-but-unusual entries as REVIEW. A variant nobody has published yet will not match. A clean result means no known indicator matched. It does not prove the machine is clean.