A recent surge of supply chain attacks is targeting the npm ecosystem through a self-replicating malware operation known as CanisterWorm. This threat, associated with a cyber group called “TeamPCP,” infiltrates legitimate publisher accounts to deploy malicious package versions, effectively turning trusted development tools into carriers for credential-stealing code.
Initial Discovery and Scope of CanisterWorm
CanisterWorm was first brought to light by security researchers at Socket and Endor Labs, who identified a pattern of harmful package updates affecting various npm publisher accounts. The malware skillfully disguises itself within what seem to be standard SDK version updates, allowing developers to unwittingly install it without suspicion.
JFrog researchers have detected new, previously unreported compromised package versions linked to the CanisterWorm attack, broadening the campaign’s known impact. Their ongoing monitoring efforts uncovered additional affected packages across multiple namespaces, including those managed by @emilgroup and @teale.io, which had previously gone unnoticed in public disclosures.
Mechanics and Effects of the Attack
The consequences of a successful CanisterWorm infection extend far beyond a single machine. Once a developer installs a tainted package, the malware deploys a Python backdoor on the host, harvests npm authentication tokens, and uses these credentials to autonomously propagate itself to every package maintained by the compromised developer. This chain-reaction capability allows a single infiltrated developer account to become a launchpad for spreading the infection to numerous downstream packages, putting a vast range of dependent projects and their users at immediate risk.
CanisterWorm is particularly challenging to detect and contain due to its seamless integration into standard development workflows. By camouflaging itself within version updates and utilizing decentralized infrastructure for command transmission, it avoids the typical indicators that most security tools rely on, expanding its reach quietly before detection.
Infection Chain and Recommended Countermeasures
The infection process begins when a developer executes npm install on a compromised package. An embedded malicious postinstall hook in the package.json file automatically executes, deploying a Python backdoor on the host system without visible alerts. On Linux systems, the worm registers a persistent background service named pgmon via systemd, ensuring it remains active through system reboots.
Once established, the backdoor communicates with a decentralized, blockchain-hosted endpoint that serves as a command-and-control server, blending malicious traffic with ordinary web requests and complicating detection. Secondary payloads are stored in /tmp/pglog, with the worm tracking its execution state in /tmp/.pg_state.
Developers using any of the identified compromised package versions should consider their environments compromised. Immediate action is required, including rotating all npm publishing tokens stored in .npmrc files, environment variables, and CI/CD pipeline secrets. On Linux, the pgmon service must be stopped and disabled using systemctl, and associated files and directories should be completely removed. Temporary files /tmp/pglog and /tmp/.pg_state should be deleted, and affected node_modules directories should be purged and rebuilt from safe package versions. Developers with stolen tokens must manually remove compromised package versions from the npm registry to protect users from installing infected releases. Setting npm config set ignore-scripts true globally is advised to prevent future silent postinstall hook executions, providing a defensive measure against such supply chain attacks.
