As we are currently adding npm audit pipelines to our frontend projects, we started a discussion on the necessity of these pipelines. While the step to detect vulnerabilities and prevent their deployment is a good choice, the real culprit is a totally different one in my opinion. So, throw away the npm audit pipeline and focus on the real problem: Avoiding updates.

What is the benefit of npm audit?

In theory, npm audit is meant as a quick check for the existence of vulnerable packages specified in your package.json. In practice, it’s used in a lot of projects as a feel-good approach to write slogans like “We run automatic tests against our codebase to guarantee the safety of your data”. This could not be further from the truth.

npm is and will never be able to guarantee absence of security issues with one quick command. If we take a look at one project I am currently working on, we can see the problem in its purest form:

Critical vulnerabilities when running npm audit
Critical vulnerabilities when running npm audit

This looks critical, right? 26 critical vulnerabilities, oh my! Best to shut prod down right away, at least nothing evil can happen to our data then!

But wait.

Where do these vulnerabilities come from? Let’s take a look and run this again, but now we exclude our dev dependencies and tool chain by using npm audit --omit dev:

No packages are vulnerable when excluding devDependencies
No packages are vulnerable when excluding devDependencies

Now, here we see the first problem of npm audit: it does not say what vulnerabilities your application has. This can only be done by a team of IT security professionals, which examined your application code-wise and pentested it.

Instead, npm audit only checks your installed packages against a list of known vulnerabilities. It does not care for real-world applications, so to say.

But your installed packages are theoretically vulnerable, there’s no way around that. But why?

Finding the true culprit

If we investigate further, we can see that most of the time, the fixes for our vulnerabilities are already available on npm. Since a long time. So why did we run into all those vulnerabilities nonetheless?

Most of the time, a project is finished at some point and then transitioned into a special ops mode. Now, only new features and bug fixes are implemented from time to time. There’s no real development going on, and when the customer wants X and Y as new features you don’t start with upgrading your packages, right?

This leads us to the real problem; out- and deprecated packages. Let’s check these by running npm outdated:

npm outdated shows about 3000 outdated packages.
npm outdated shows us more outdated packages than my terminal can display in one buffer

So, so many outdated packages! Counting them with npm outdated --all | wc -l reveals that there are in fact 3312 outdated packages in my project. Many come as cross dependencies from other, already deprecated, packages.

Conclusion

In my opinion, we should move away from pipelines checking for vulnerabilities. Instead, we should pro-actively search for available updates instead. This also eases the prevention for huge legacy projects that are unmaintainable at some point, just because there have been no updates in the past years and now you would have to migrate from angular v4 to angular v17. This case might be taken from a real-world example.

One solution would be dependabot. It’s a bot for github, which you have probably seen before in a github repository of a larger npm package. This bot creates a pull request when a dependency of the project becomes outdated. A nice solution if you use github!

Another solution would be to adapt or create a pipeline that does not just search for vulnerable packages but also searches for available updates as well.

Leave a Reply

Your email address will not be published.