Securing npm package releases — highlighting common threats and taking steps to mitigate them.
In the second scenario, the fix is less straightforward. Yet, it’s essential to protect your code from bad actors who may infect or expose your work to different vulnerabilities. And to do that, you must understand the threats involved in releasing code through node package manager (npm) or other registries and then develop the steps to mitigate them.
Defending against common threats
There are quite a few threats to maintaining any project in the open-source ecosystem. Listed below are some of these and issues specific to the npm ecosystem.
Code obfuscation attack
A bad actor can publish a package with obfuscated code that exploits anyone who uses your code. You may be auditing or looking over the repository and miss that when the package dependency is installed, it uses an obfuscated version instead. We can minimize this threat vector by:
- Make sure not to use any dependency with obfuscated code
- While reviewing the packages, audit the compiled and obfuscated code
- If needed, compile that dependency locally and see if it matches the same output
Git impersonation attack
Git allows any user to make any commit with the author and email address set to any (valid) value. One can also set the commit date as long as it’s a valid timestamp. So, in this case, an attacker can push a commit in a long going pull request (PR) with the same author name/email address in a public repository. This may end up with an unintended inclusion of a code snippet. Here’s how to protect against this:
- Make sure all release branches are locked
- Verify the authenticity of your organization’s git users carefully
- Enforce the rule that all users must sign commits with their GPG keys
- Never merge any PR which include any unsigned commits
Typosquatting and combosquatting are examples of software supply chain attacks, where malicious packages are published with the intent of free-riding on the trust people put onto their third-party components. The use of open-source packages is quite popular in the NodeJS ecosystem, and it all lies in the trust of the developers. A few years ago, a fake babelcli was published to attack the original babel-cli and gained a couple of downloads in a few weeks. Here’s what to do:
- While using dependencies, double and triple check the dependency’s name
- Verify the dependency info with the npm info
- Scan exiting public registry for the package names similar to your library
- Ask the community to report any package which they found confusing or with a similar name
- Setup a bot or service to monitor new package registration for the same purpose
Account takeover (ATO) attack
Account takeover fraud is a type of cybercrime or identity theft where a malicious third party gains access to (or “takes over”) an online account. In the npm ecosystem, ATO is less frequent, but the impact is widespread.
Once an ATO happens, the attacker releases a patch version with infected code, and since most of the JS ecosystem depends on auto-version updates, the infected package spreads quickly. In the past, we saw ua-parser-js, coa, and rc packages like this. It does not matter if you use npm or Github registry. Both can affect ATO. To mitigate this threat:
- Ensure that all users in Github use 2FA.
- Ensure that all users on npm use 2FA.
Each time you login to the npm CLI, a security token is created. That token can perform registry-related actions during CI and automated processes. It’s possible that a token gets compromised during some data transfer or shared system usage. We can defend ourselves by:
- Limit who has access to the npm registry
- When one user is not intended to publish, always create a “read-only” mode npm token.
- When one user is intended to publish, packages must assign a token to a particular IP. `npm token create — cidr=126.96.36.199
Audit and monitor vulnerabilities
The npm ecosystem is vast, and the more open and diverse it becomes, the more prone it is to vulnerabilities. In the past, most popular npm packages were found to be vulnerable. Some notable examples are request and jsonwebtoken. So staying on top of the security for all our dependencies would allow for a timely alarm before a new version injects a malicious code into your library. Therefore, it’s important to:
- Keep updating your dependencies to get more stable and secure versions
- Use a vulnerability monitoring service like sync.io to keep an eye on all dependencies
Avoid publishing sensitive data on Github
It’s not uncommon for developers to have sensitive data on their development machines — for instance, API keys. And this opens the possibility that such information can be mistakenly committed to Github or any other version control you use. To prevent this:
- Create a special file or structure for sensitive data. E.g. a directory `.secrets/keys`. This will ensure everyone knows if they want to use some keys that can be put in this file.
- Add such files to ‘.gitignore’ to make sure these never become part of the SVC.
- While doing code reviews on Github, pay special attention to collapsed files. In Pull Request review mode, Github collapses very large files, and such files are often accidentally skipped during a review.
The above mitigation steps and guidelines are not a bulletproof plan to protect your npm package release but will at least protect you from commonly known factors. As a package release manager, you must always keep a vigilant eye on your package releases. Having a well-defined security and vulnerability reporting mechanism for the community can also be a good addition. We wish you all safe releases!
Disclaimer: The suggestions above cover some of the fundamentals and are not fit for every project or situation.
ChainSafe is a leader in blockchain development and infrastructure solutions for Web3. We’re working toward a more decentralized future by building client implementations for Ethereum, Filecoin, Polkadot, and Mina. We’re also maintaining the Web3.js library, working on a gaming SDK that connects NFTs to Unity, building a distributed cloud storage application, and bootstrapping a multi-chain bridge. To learn more, click here.
Want to help build the foundations of Web3? Join us!
Have a question, comment, or suggestion? Drop into our Discord and join the conversion! We’re also always looking for talented people. Check out our open positions and get in touch ➡️➡️ firstname.lastname@example.org
Special thanks to M. Junaid Taj and Colin Adams for their help writing this article.