In October 2021 attackers took over the maintainer's npm account and published three malicious ua-parser-js releases: 0.7.29, 0.8.0 and 1.0.0. Clean versions are 0.7.30, 0.8.1 and 1.0.1. Any machine that installed a bad version should be treated as compromised, and its secrets rotated.
Facts from CERT-EU
CERT-EU advisory 2021-057 says CISA alerted on 22 October 2021 and CERT-EU published on 26 October. The attackers took over the developer's account on 22 October and published three malicious releases of a widely used browser user-agent parsing library.
What the bad versions did
A preinstall.js script ran during install.
- On Linux, it launched a shell script that downloaded an XMRig Monero cryptominer, skipping devices located in Russia, Ukraine, Belarus and Kazakhstan.
- On Windows, a batch file downloaded the same miner plus a password stealing DLL, run with
regsvr32. The advisory says it used PowerShell to harvest Windows Credential Manager secrets and targeted FTP, VNC, messaging, email clients and browsers.
The install script is the key detail. The malicious code ran at install time, before any application code used the library, and on developer laptops and build servers as well as production.
Cleanup list
- Upgrade to 0.7.30, 0.8.1 or 1.0.1.
- Find every machine that installed a bad version. Check lockfiles, build logs and container layers from the exposure window.
- Search devices and firewalls for the indicators in the advisory: file hashes, the
preinstall.jsfile and the listed domains and addresses. - Delete matching files and, because the stealer targeted stored credentials, treat the host as compromised.
- Rotate passwords, keys and tokens that were available on that host, including cloud and registry credentials.
- Rebuild affected CI runners from a clean image.
CERT-EU's own recommendations are shorter: upgrade, hunt for indicators, delete matches and change passwords, keys and tokens.
How to tell if you were exposed
Start with your lockfiles. Search every repository, including old branches, for the three bad version numbers. Then look at build logs from 22 October 2021 onward for installs of the package, since a build server may have pulled a bad version even if the lockfile in the repository never recorded it. Developer laptops are the hard part, because installs there leave no central record. Ask teams to check their local package caches and shell history if the package was in use.
If the package was a transitive dependency, the version in your tree depends on the range your parent package allowed. A range that accepts new minor versions would have pulled a malicious release during the exposure window.
Reducing exposure to this class
- Disable install scripts where you can. Many package managers can skip lifecycle scripts, and CI usually does not need them for every package.
- Pin and delay. Use lockfiles and wait a short period before adopting brand new releases.
- Use strong multifactor authentication on maintainer accounts if you publish packages.
- Scan on install, not only at release. A check at pull request time can catch a bump before it lands.
Related: lessons from the ua-parser-js compromise. Safeguard's gates and dependency scanning can block a flagged version in a pull request, and you can try a free scan at gold.safeguard.sh/scan.
Quick check
Which versions were malicious?
0.7.29, 0.8.0 and 1.0.0, per CERT-EU.
Is upgrading alone enough?
No. The password stealer means you should rotate credentials from affected hosts.
Sources
Last reviewed: 19 October 2026.