npm: Threats and Mitigations
We put together this page to give an overview of the most common attacks npm faces, a high-level description of how we mitigate those attacks, and links to more information.
This is the most common attack, not just on npm but on any web service. The best way to protect your account is to enable two-factor authentication (2FA). The strongest option is to use a security-key, either built-in to your device or an external hardware key; it binds the authentication to the site you are accessing, making phishing exceedingly difficult. Not everyone has access to a security-key though, so we also support authentication apps that generate one-time passcodes for 2FA.
Because of how common this attack is, and how critical npm packages are to the broader software ecosystem, we have undertaken a phased approach in mandating 2FA for npm package maintainers. This has already rolled out to the top-100 package maintainers and top-500 package maintainers, and in the near future, maintainers of all high-impact packages (those with 1 million+ weekly downloads or 500+ dependents) will be enrolled in mandatory 2FA.
We also recognize that passwords aren’t going away any time soon. For users that don’t opt-in to 2FA, we do an enhanced login verification with a one-time password sent to their email to protect from account takeover.
Another method used to take over an account is by identifying accounts using an expired domain for their email address. An attacker could register the expired domain and recreate the email address used to register the account. With access to an account's registered email address an attacker could take over an account not protected by 2FA via a password reset.
When a package is published the email address associated with the account, at the time the package was published, is included in the public metadata. Attackers are able to utilize this public data to identify accounts that might be susceptible to account takeover. It is important to note that the email addresses stored in public metadata of packages are not updated when a maintainer updates their email address. As such crawling public metadata to identify accounts susceptible to expired domain takeover will result in false positives, accounts that appear to be vulnerable but are not.
npm does periodically check if accounts email addresses have expired domains or invalid MX records. When the domain has expired, we disable the account from doing a password reset and require the user to undergo account recovery or go through a successful authentication flow before they can reset their password.
Attackers may attempt to trick others into installing a malicious package by registering a package with a similar name to a popular package, in hopes that people will mistype or otherwise confuse the two. npm is able to detect typosquat attacks and block the publishing of these packages.
A variant of this attack is when a public package is registered with the same name of a private package that an organization is using. We strongly encourage using scoped packages to ensure that a private package isn’t being substituted with one from the public registry. While npm is not able to detect dependency confusion attacks we have a zero tolerance for malicious packages on the registry. If you believe you have identified a dependency confusion packages, please let us know!
Rather than tricking people into using a similarly-named package, attackers also try to add malicious behavior to existing popular packages. In partnership with Microsoft, npm both scans packages for known malicious content, and runs the packages to look for new patterns of behavior that could be malicious. This has led to a substantial reduction in malicious content in npm packages. Furthermore, our Trust and Safety team checks and removes malicious content reported by our users. Similar to dependency confusion attacks, we are constantly updating our detection services with new examples, so if you think a package contains malicious behavior, please let us know!