In November 2021, two of the most widely used packages in the npm registry — coa and rc — were hijacked on the same day and turned into delivery vehicles for Windows password-stealing malware. The coa rc npm hijack became one of the clearest demonstrations yet that a single compromised maintainer credential can instantly threaten millions of downstream builds. coa (Command-Option-Argument), a command-line parsing library pulled in by projects like Vue CLI, was downloaded roughly 9 million times a week. rc, a lightweight configuration loader buried deep in the dependency tree of countless Node.js tools, saw over 14 million weekly downloads. When attackers slipped malicious versions of both into the registry within hours of each other, they didn't just poison two packages — they poisoned a huge, invisible slice of the JavaScript ecosystem that had never audited either dependency directly.
What Was the coa rc npm Hijack?
The coa rc npm hijack was the near-simultaneous takeover of the coa and rc npm packages on November 4, 2021, used to publish trojanized releases to unsuspecting developers. Within a short window, malicious versions of coa (including 2.0.3, 2.0.4, 2.1.1, 2.1.3, 3.0.1, and 3.1.3) and rc (including 1.2.9, 1.3.9, and 2.3.9) appeared on the npm registry. Neither package had seen a legitimate release in months, which made the sudden burst of new version numbers an immediate red flag for anyone paying close attention. Because coa and rc are transitive dependencies — pulled in automatically by other packages rather than installed directly — most affected developers had no idea either library was even part of their build until npm install started behaving strangely or CI pipelines started failing outright.
How Did Attackers Take Over the Maintainer Accounts?
Attackers gained control by compromising the npm publishing credentials tied to the accounts that maintained both packages, a textbook case of maintainer account takeover. Security researchers who investigated the incident noted that coa and rc shared overlapping maintainers on npm, which meant a single compromised credential — whether obtained through credential stuffing, a reused password from an earlier breach, or a phishing attempt targeting npm login pages — could reach into more than one high-traffic project at once. This is the structural weakness that made the coa rc npm hijack so efficient for the attacker: rather than needing to breach two separate developers' security, one set of stolen credentials on the npm registry unlocked publish rights to two packages with a combined weekly download count north of 20 million. npm's publishing model, like most package registries at the time, relied heavily on password-based or lightly protected accounts rather than mandatory hardware-backed two-factor authentication for high-impact maintainers.
What Did the Malicious Package Versions Actually Do?
The malicious versions ran a post-install script that attempted to install a password-stealing trojan on Windows machines. Once npm install triggered the tampered package's install hook, the script downloaded an additional payload designed to harvest saved credentials from browsers and other local applications, disable or evade Windows Defender, and exfiltrate the stolen data to attacker-controlled infrastructure. The payload was Windows-specific, meaning Linux and macOS developers and CI runners were largely spared the credential-theft component but often still hit broken builds, since the install script itself frequently errored out or hung on non-Windows systems. That side effect is part of why this malicious package was caught so quickly: it broke things loudly rather than staying quiet. The incident arrived less than two weeks after a similar, likely related compromise of the ua-parser-js package, reinforcing that this was part of a broader wave of npm supply chain attacks targeting the same class of victims in late 2021.
How Was the Attack Discovered and Stopped?
The attack was discovered within hours because developers noticed unexpected version bumps and sudden install failures and reported them publicly on GitHub and social media. Once flagged, npm's security team moved quickly: the malicious versions of coa and rc were pulled from the registry, and in the interim both packages were briefly unpublished entirely to stop further installs while the situation was triaged. Maintainers and npm worked to restore clean, verified versions and published security advisories detailing the affected version ranges so teams could check their lockfiles. For most organizations, remediation meant auditing package-lock.json or yarn.lock files for the specific malicious version strings, purging local npm caches, rotating any credentials that might have been exposed on affected Windows machines, and pinning dependencies to known-good releases going forward.
Why Does This Incident Still Matter for Node.js Supply Chain Security?
This incident still matters because it proved that popularity and maturity offer no protection against a single stolen credential, and the same pattern keeps recurring across the npm ecosystem. coa and rc were not obscure or poorly maintained packages — they were foundational utilities embedded in the dependency graphs of major Node.js frameworks and tooling, exactly the kind of "boring, stable" dependency that teams assume is safe precisely because it never seems to change. The coa rc npm hijack showed that this assumption is a liability: an attacker doesn't need to compromise the flashy, high-visibility project you audit carefully, only the quiet transitive dependency three levels down that nobody has looked at since it was first installed. Years later, npm maintainer account takeovers remain one of the most common root causes behind malicious package incidents across the JavaScript ecosystem, because registries still largely trust whoever holds a valid publish token.
How Safeguard Helps
Safeguard is built for exactly this scenario: the moment a trusted npm package quietly turns hostile because someone else's account was taken over. Safeguard continuously monitors your software supply chain for anomalous publishing activity — including sudden version bumps on long-dormant packages, new maintainers appearing on high-impact dependencies, and install scripts that reach out to unexpected network destinations — so a coa rc npm hijack-style event gets flagged before npm install ever runs in your pipeline. Rather than relying on developers to notice broken builds or scan social media for advisories, Safeguard correlates registry metadata, package behavior, and your actual dependency graph to surface transitive risk you didn't know you had.
Beyond detection, Safeguard helps teams enforce guardrails that make maintainer account takeover far less effective as an attack path: policy-driven approval gates for new or unusual package versions, automated blocking of known-malicious package hashes and version ranges, and visibility into every transitive dependency pulling code into your Node.js builds. When an incident does hit the wild, Safeguard's alerting gives security teams the same early-warning signal that caught coa and rc in hours rather than days — but without depending on luck, a broken CI job, or a developer's tweet to trigger the response.