CanisterWorm Uses Compromised npm Publisher Access to Backdoor Packages

Summary
Socket's investigation found CanisterWorm replacing legitimate npm packages with a postinstall loader and Python implant that persists via systemd --user, polls an ICP canister for payloads, and republishes malware using compromised npm publishing access.
Key points
- Socket reports a compromise affecting legitimate packages under the @emilgroup scope and @teale.io/eslint-config; malicious releases replaced package functionality with malware.
- A postinstall hook launches a loader that installs a Python implant as a persistent systemd --user service named pgmon.
- The implant polls an Internet Computer Protocol canister at tdtqy-oyaaa-aaaae-af2dq-cai[.]raw[.]icp0[.]io for second-stage payload URLs, then downloads and runs binaries.
- The deploy.js worm uses npm publishing tokens or equivalent CI/CD access to enumerate publishable packages and republish malicious versions; later variants use the latest tag.
- The investigation describes an initial staging phase followed by weaponized releases with an embedded Python dropper and standardized persistence.
- Socket assesses the publisher-space compromise and propagation model with high confidence but has not conclusively attributed the activity to a threat actor.
Article Details
- Attack Vectors
- Malicious releases of legitimate npm packages used postinstall hooks to launch an installer and Python implant.
- The implant established user-level persistence through a systemd --user service named pgmon.
- The implant polled an ICP canister for second-stage payload URLs, then downloaded and executed binaries.
- The deploy.js worm used compromised npm publishing tokens or equivalent CI/CD publishing access to republish malicious package versions across accessible packages.
- Defensive Notes
- Socket users can check for impact under Threat Intel → Campaigns on Socket’s public CanisterWorm campaign page.
- The article identifies compromised releases under @emilgroup and @teale.io/eslint-config; review installations of the package versions listed in the article.
- The article reports npm token harvesting from .npmrc, environment variables, and npm configuration, but provides no specific remediation steps.
Indicators of compromise
| Type | Indicator | Context |
|---|---|---|
| URL | hxxps[:]//tdtqy-oyaaa-aaaae-af2dq-cai[.]raw[.]icp0[.]io/ | C2 dead-drop URL polled by the Python implant to retrieve second-stage payload URLs. |
MITRE ATT&CK
T1059 · Command and Scripting InterpreterAn npm postinstall hook invoked node index.js to launch the loader.T1078 · Valid AccountsThe attacker appears to have used valid npm publishing tokens or equivalent CI/CD publishing access to publish malicious releases.T1102 · Web ServiceThe implant polled an ICP canister used as a rotatable dead-drop C2 channel.T1105 · Ingress Tool TransferThe Python implant downloaded binaries from URLs returned by the ICP canister and executed them from /tmp/pglog.T1195.001 · Compromise Software Dependencies and Development ToolsThe attacker replaced legitimate npm package contents with malicious code and republished releases through compromised publisher access.T1543.003 · Windows ServiceThe loader created and enabled the user-level pgmon.service systemd unit with Restart=always.T1552.001 · Credentials In FilesA reported @teale.io/eslint-config variant harvested npm tokens from .npmrc, environment variables, and npm configuration.
People
Malware
Products
npmSocket’s Threat Research Team uncovered a worm-enabled npm supply chain attack that compromised legitimate publisher namespaces including @emilgroup and @teale.io, replacing package contents with a Python implant thatsystemdThe campaign, dubbed CanisterWorm, uses postinstall hooks, a systemd –user persistent service named pgmon, and a deploy.js republishing worm that leverages npm publishing tokens (often published with –tag latest) to
