Securing NodeJS Projects Dependencies
In a world where security becomes more important by the minute and new NPM modules and versions are released by the second, we need to keep a keen eye on all the third party code we use in our daily life. Events like the Event-Stream Incident demonstrate how important the topic is. But still many developers and companies disregard security as something that can always be done after the next feature is ready.
This article will not cover application security, but rather on how to ensure you are not running into problems with 3rd party software you are using.
Getting an overview
There is a saying in Information Security called:
You can’t protect what you can’t see.
So, the first thing you do is getting an overview on your current situation. Luckily with NPM since version 6, it will tell you every time you run any npm install command about security vulnerabilities.
For demonstration purposes I will use handlebars in the following examples. I have no personal issue with handlebars. I just picked this projects as it has around 10 million downloads per week (as of writing this article). To the handlebars maintainers: You do a great job in keeping the project up to date and if you feel offended by me taking you as an exmaple, I am happy to send you a cake of apology :)
Now to our example. If you run npm install handlebars@4.0.4 it will display the security results after the installation.
For existing projects you can just run npm audit to get an overview about our current situation.
NPM will create a security report that looks like this for the example above.
I have redacted the output to not pollute this post. But for every vulnerability, you will get an indivual box telling you what exactly the problem is, including a link to NPM with advise on how to approach the related issue.
Let NPM help you
As you might have seen in the examples above, NPM already gives you cli commands to run, to fix many of the occurences. With the npm audit fix command you can install any compatible updates to vulnerable dependencies without breaking your code. And this is also the first commit you can make to your projects to fix many of the vulnerabilities.
With this first step you already got rid of (hopefully) many security issues. In some of my company’s projects they were 700+ vulnerabilites on a single project. After running npm audit fix this number got reduced to less than 100!
The diligent part
Unfortunately sometimes NPM is not able to fix all the issues you are facing due to major version updates including breaking changes. To stay with our example, let’s assume you are using handlebars at version 3.0.7. The output after the installation will look like this:
At first glance you have one vulnerability less than with version 4.0.4. But when you run npm audit the security report will look different.
This time NPM will not offer you to run npm audit fix as you need to update handlebars to the next major version which might break your code. However, they suggest to install the handlebars module with the current latest version. Now it depends on the test coverage of your project and of the maintainers documentation. Handlebars has (as many other projects) release notes, detailing changes with each version update. On the major version update for 4.0.0 you can also find Compatibility notes helping you to migrate from version 3.
If you are lucky, all projects where you need to update major versions offer the same kind of documentation. Some projects also offer detailed migration guides. If that is not the case, you might get lucky with googling the version you want to migrate from and find help as the NPM community is posting those guides everywhere on the web.
As a last resort you can also reach out to the maintainers for help.
After you are done with the major versions, make sure to put them in separate commits as it makes reviewing your changes easier for your colleagues.
Never again
So you fixed all your issues and the result of npm audit looks like this:
We want to ensure that nobody is committing vulnerable packages to your project. The first step to take is make it easy for your colleagues to be aware of the usage of npm audit. In our example we will introduce a NPM script to test for vulnerabilities.
You might think that this feels kind of redundant as we just map the NPM command to a NPM script, but seeting this step alongside other like test or lint gives it more visibility. This step is also handy in case you have some modules you serve from private registries that do not support NPM audits.
In that case you would need to update the script a bit further:
You can now go ahead and either utilize git-hooks or CI/CD pipelines to integrate this step. In our company we run this NPM script on feature branches to ensure that those have a clean state. However, we do not run them on master or release branches as new security vulnerabilities can pop up anytime and reopening merge request for those scenarios slow you down more than you want. You can also mark those pipeline step to be allowed to fail. The important part here is, that you gain even more awareness for your current security status.
Conclusion
Coming back to our initial statement “You can’t protect what you can’t see.” The most important point I want to highlight is, that being aware of your security issues is already valuable enough even without fixing all of them.
The first step you can take in your team or work environment is to raise awareness for vulnerabilities. Security these days is not the most difficult topic to work on, you just need to start doing it, one vulnerability at a time.
Thank you ❤
Further reading
NPM Audit CLI
Auditing package dependencies for security vulnerabilities