devtake.dev

Another npm worm: CanisterWorm hits 16 Namastex packages and reaches PyPI on the same hop

Socket flagged a self-propagating worm in @automagik/genie, pgserve, and 14 sibling Namastex Labs packages. It steals 40 credential categories and republishes itself.

Luca Reinhardt · · 4 min read · 4 sources
Socket security research card promoting the CanisterWorm Namastex compromise analysis.
Image via Socket · Source

A self-replicating npm worm hijacked 16 packages tied to AI agent startup Namastex Labs starting on April 21, including the agent framework @automagik/genie and the database utility pgserve. Socket and StepSecurity caught it on April 22 and named the malware family CanisterWorm.

The first poisoned release, [email protected], hit npm at 22:14 UTC on April 21, and Socket says the count is climbing as the team works through the registry. Socket wrote in its analysis that the payload is “a self-propagating worm rather than just credential theft”, designed to turn a single compromised developer machine into the next launchpad. This is the third such npm campaign in roughly six weeks. Different operators, similar shape, same root cause: postinstall hooks that run arbitrary code on npm install and packages that republish themselves to other registries when they find tokens.

What’s compromised

Socket’s IOC list names seven malicious version ranges across six packages, with the count climbing as the team works through the registry:

  • @automagik/genie versions 4.260421.33 through 4.260421.39, around 6,744 weekly downloads.
  • pgserve versions 1.1.11 through 1.1.13, roughly 1,300 weekly downloads.
  • @fairwords/websocket 1.0.38 and 1.0.39.
  • @fairwords/loopback-connector-es 1.4.3 and 1.4.4.
  • @openwebconcept/design-tokens 1.0.3.
  • @openwebconcept/theme-owc 1.0.3.

Namastex Labs builds agent tooling, so the affected packages skew toward developer environments that already have privileged tokens lying around: GitHub PATs, AWS keys, OpenAI and Anthropic credentials, kubeconfig files. That is the worm’s actual target, not the user.

What the worm does on install

The payload runs from a postinstall script, which means npm install is enough to trigger it. Socket’s reverse engineering describes four staged actions inside the bundled JavaScript: regex-sweep credential harvest, crypto-wallet sweep, exfiltration, and self-propagation. The credential sweep covers about 40 categories, including:

  • Environment variables matching secrets, tokens, cloud keys, and LLM platform keys.
  • .npmrc, .git-credentials, .netrc, and SSH private keys.
  • AWS, Azure, and GCP credential files.
  • Kubernetes, Docker, Terraform, Pulumi, and HashiCorp Vault material.
  • Browser login storage and wallet files for MetaMask, Phantom, and the major chains.

The exfiltration channel is what makes this campaign distinctive. Instead of pure HTTPS to a stealer panel, CanisterWorm posts to two endpoints: a conventional telemetry.api-monitor[.]com URL, and a hardcoded Internet Computer Protocol canister at cjn37-uyaaa-aaaac-qgnva-cai. ICP canisters are decentralized smart-contract endpoints that are harder to take down than a single VPS. The Register notes the canister handle differs from the one Socket associated with the original CanisterWorm campaign in March, which Socket was careful to flag: the operator looks related but is “stopped short” of being attributed to TeamPCP outright.

The fourth action is the propagation step. If the host has an npm publish token, the worm reuses it to publish a poisoned version of every package the token can write to. If it finds a PyPI token, it switches ecosystems: the Python equivalent of the worm gets uploaded as a fresh package under the victim’s identity. The Hacker News confirmed that npm-to-PyPI propagation is built into the payload, which is what landed it on the same Apr 22 reporting cycle as the wave of xinference PyPI compromises.

Why this keeps happening

Three self-spreading npm campaigns since March. The Trivy hijack in March used a stolen GitHub PAT to retag releases. The Shai-Hulud “Third Coming” run earlier this month rode through the Bitwarden CLI. CanisterWorm picks up where both stopped, and by Socket’s read shares code lineage with the TeamPCP/Trivy operator, including a literal “TeamPCP/LiteLLM” string baked into the propagation routine.

The structural problem is that npm runs install scripts by default, accepts publish writes from any token with package permissions, and gives you no friction between “I logged in to deploy a release” and “every other package this account can touch just got rewritten.” None of the recent campaigns required a clever exploit. They required one credential and one npm publish call.

What this means for you

If you’ve installed any of the listed package ranges since April 21, treat the host as compromised. Rotate every npm token, GitHub PAT, cloud credential, and SSH key the user has touched. Then audit the last week of npm publish events on any account where you held a token, because the worm’s propagation step is silent and the only signal you’ll get is an unexpected version on a package you maintain.

The longer-term fix is the boring one: pin by integrity hash, not by tag; turn on npm’s required-2FA-on-publish for every maintained package; and enforce --ignore-scripts in CI for any install where you don’t actually need lifecycle hooks. Most builds don’t. The reason supply-chain worms keep working is that most teams haven’t flipped that switch on the path that runs on every push. CanisterWorm won’t be the last. It probably won’t be the last this month.

Share this article

Sources

Mentioned in this article