Imagine that you’ve been working on a node.js project for a few years now. You started or joined it when you were younger. The code works, you can vouch for that it’s good and secure for yourself and your team. But how do you validate all those NPM modules that saved you so much time and effort over the years? It works, nobody has hacked you yet, so why should you bother?
Unfortunately, ignoring security is becoming pretty much impossible for developers. In recent years the programming landscape has shifted towards higher and higher security standards. With more than 50% increase in data breaches the last five years and an avalanche of cybercrime attacks being registered, keeping online services secured and operational is slowly taking more and more time from development teams.
The costs of a data breach can cripple a well-established company, not to mention potentially being a death sentence for a startup. And that is without mentioning the governmental regulation introduced with EU’s GDPR act and GDPR inspired laws across the globe. This is why it’s very important to take efforts on every level to reduce and mitigate the security threats of the software you develop.
Tools for checking packages
Let’s start with some simple commands you can just add to your build script or as a CI/CD step.
The dedupe command simply tries to simplify your dependencies by moving them up the tree. In essence, trying to have a single compatible dependency that can be used by more packages, instead of each having its own slightly different version. Fewer versions to deal with simply give fewer attack vectors through said dependency (newer versions tend to have fixes for already known and published vulnerabilities).
A very powerful command that scans your project for all known vulnerabilities and provides you with a security report as well as potential fixes. In some cases it can even update packages for you. In others, it merely tells you what to do in order to fix it. While it is very powerful, it also has its limits. Namely, it can only check against known vulnerabilities reported to the npm registry. You are out of luck for all vulnerabilities not yet validated by them.
OWASP dependency check checks the dependencies against a publicly available database with known vulnerabilities. It has a CLI tool which locally stores the whole database against which it checks. This makes it appropriate for systems in which you don’t want to give full access to.
This command-line utility allows you to both check for bad dependencies and will prompt you to confirm if it notices that you are trying to install a package with known vulnerabilities.
Here you can find a curated list of different security-oriented node.js resources. It may be useful for fixing or mitigating issues and vulnerabilities for cases where the simple update is not that easy to do.
Going beyond automated checks
Besides things you can add to your general code workflow, you might periodically want to go deeper into the analysis of your packages. Try answering the following questions for your project:
- What am I using this module for? Is it still necessary?
- Are there any cases of different modules (or our code) being used to solve the same problem?
- Which packages bring in most submodules? Can I replace them with some “flatter” packages?
- Are they all still in active development? Which ones haven’t been updated for a long time or don’t have any active developers?
- Take a look at their issues/bug tracker, are there any reports of vulnerabilities or bad code?
- Are they publishing test coverage, passing and/or any other code quality metrics?
The questions above will help you evaluate if any of the packages have to be updated or replaced with alternatives or even coded by your team. But you might have to go even further. The questions above focus on a few attack vectors; mainly cases where developers intentionally or by mistake have introduced vulnerabilities into their codebase. But what about if the user account of the publisher gets compromised?
Bad and duplicated passwords are a reality that impacts the security of every online service, npm registry included. If you have a publisher’s password you could git clone his code, add your malicious code, build and publish it to the NPM registry. Everything would look fine, and it could be months and millions of downloads before someone notices that there’s anything wrong. One case of this was a package that was stealing bitcoins from miner’s wallets for almost 3 months before being detected. Currently, there is no good way of verifying that what is published is what is shown on the project’s Github.
So, what to do?
There are a few ways you could go about validating for the above:
- Compare git commit hashes between GitHub and the version you download from the registry.
- Downloading the source and building it yourself, and then comparing it to the downloaded package from NPM. Running tests and benchmarks against both versions and looking for any change in results and performance could reveal a code discrepancy that may indicate a potential for malicious code.
Look for a new possible attack vector
This post started with some simple steps you can take to increase security. Everything beyond tends to get more complicated, and is hard to do on a day to day basis on a project. Besides knowing what vectors can be used to compromise your application right now, you also have to be mindful of potential future attack vectors (that are still unknown or never attempted against npm registry/packages). And, sadly, for this, there is very little you can do besides reading blogs, attending conferences, looking for official announcements or having a dedicated security specialist do it for you.
This is where tools like ours can come in handy. You could, in theory, reimplement the whole checking stack by researching all attack vectors, vulnerability reporting sites, test cases, benchmarks for code as well as create required scripts to run and CI/CD pipelines to automate it. But, all that work would only bring you to the current state of the art. Besides, it would require additional maintenance effort just to keep it running.
But with a cloud-based vulnerability scanner, you are not only subscribing to the current state of the art vulnerability checking. You are also delegating all the expertise and research that you or your team would have to acquire and constantly stay updated on in order to have an in house solution for security validation.