DEV Community

Brandon Benefield
Brandon Benefield

Posted on • Edited on

NPM Audit Fix Fixing NPM Dependencies Vulnerabilities

TLDR;

  • Run the npm audit command
  • Scroll until you find a line of text separating two issues
  • Manually run the command given in the text to upgrade one package at a time, e.g. npm i --save-dev jest@24.8.0
  • After upgrading a package make sure to check for breaking changes before upgrading the next package
  • Avoid running npm audit fix --force

Vulnerabilities

Every now and then after installing your projects dependencies, npm i, you will be met with an error from NPM that looks something like

┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Low           │ Regular Expression Denial of Service                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ braces                                                       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ jest [dev]                                                   │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ jest > jest-cli > micromatch > braces                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/786                       │
└───────────────┴──────────────────────────────────────────────────────────────┘


found 62 low severity vulnerabilities in 20610 scanned packages
  62 vulnerabilities require semver-major dependency updates.

This is actually an extremely small example of a typical vulnerability warning. As you can see from the text underneath the vulnerability it says

found 62 low severity vulnerabilities in 20610 scanned packages
  62 vulnerabilities require semver-major dependency updates.

Meaning that this example would have another 61 vulnerabilities ranging from low to high with of course high being the most dangerous vulnerability. For more info on any of these vulnerabilities, there is also a link to the vulnerability on NPM inside the More Info section of the warning.

At first, it may seem confusing on how to properly fix these vulnerabilities. NPM actually provides a service built into NPM that is supposed to automatically fix these issues, npm audit fix, but I've found that this will rarely work, and will leave you with nearly just as many vulnerabilities as before. In fact, here's an example of what happened after I ran npm audit fix.

fixed 0 of 62 vulnerabilities in 20610 scanned packages
  1 package update for 62 vulns involved breaking changes
  (use `npm audit fix --force` to install breaking changes; or refer to `npm audit` for steps to fix these manually)

NPM gives us the option to use the --force flag, npm audit fix --force, but even NPM will warn you about using this flag

user@group:~/npm_project$ npm audit fix --force
npm WARN using --force I sure hope you know what you are doing.

So what are we supposed to do? If our package manager isn't able to fix these vulnerabilities then surely we're out of luck and must find a way to survive with these vulnerabilities hoping nobody decides to exploit them against our project.

The Fix

Manually upgrade the packages one at a time with the command suggested by NPM instead of running the npm audit fix --force command. For example npm install --save-dev jest@24.8.0.

First of all, I want to say that this might be incredibly obvious to those that have run into this problem before. When I first saw these, it was a gigantic list of warnings and being the lazy developer that I am, I didn't even bother to scroll through the issues.

If you just continue to scroll up inside your console to the very first issue you'll actually run into a fix and yes, as you would expect, it's as simple as updating the package that's causing the issue.

user@group:~/npm_project$ npm audit --fix

                       === npm audit security report ===                        

# Run  npm install --save-dev jest@24.8.0  to resolve 62 vulnerabilities
SEMVER WARNING: Recommended action is a potentially breaking change
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Low           │ Regular Expression Denial of Service                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ braces                                                       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ jest [dev]                                                   │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ jest > jest-cli > jest-config > babel-jest >                 │
│               │ babel-plugin-istanbul > test-exclude > micromatch > braces   │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/786                       │
└───────────────┴──────────────────────────────────────────────────────────────┘

... 61 more vulerabilities ...

Right before the vulnerability issue you'll notice the text # Run npm install --save-dev jest@24.8.0 to resolve 62 vulnerabilities which is exactly what we're looking for. You may also notice that the very next line says SEMVER WARNING: Recommended action is a potentially breaking change. Manually running this command instead of using the npm audit fix --force command lets us know exactly which packages we're updating. This is valuable for the scenario where updating these packages actually causes a breaking change.

Summary

So in the end, manually upgrading the vulnerable packages and running npm audit fix --force is going to have the same results. The only difference is that manually upgrading our packages will allow us to upgrade a single package, test for a breaking change, then update the next package, instead of just upgrading all of the packages at once, find a breaking change, then having no idea which package decided to screw things up.

Top comments (20)

Collapse
 
genster profile image
Ryan Cole

Any tips for how to update old deps inside of other packages? Most of my warnings come from larger packages that I don't have access to the internals of without significant hassle. If I update them in my repo, will the newer version I installed override the old version inside the library? Thanks!

Collapse
 
bbenefield89 profile image
Brandon Benefield • Edited

@askdesigners Yup, that's exactly what this post is about. Just like in this post, I was using jest@23.x.x and it had 62 vulnerabilities coming from multiple internal packages that jest uses.

When running the suggested command that came from NPM, run npm install --save-dev jest@24.8.0, it will then grab that specific version of jest that fixes the vulnerabilities. This means that the maintaner(s) of your package have fixed the vulnerabilities and pushed a new version of their package for you to use.

Another option, that I wouldn't recommend, is to install the vulnerabilities of the internal packages into your own project. For example, if one of your packages is reporting a vulnerability from an internal package, braces like in my example in the post, you could install the fixed version of that package yourself using npm i --save-dev braces but this could cause breaking changes.

Collapse
 
scottdotjs profile image
Scott Martin 🛠️

Hi Brandon, thanks for your post. I'm trying to fix the same vulnerability in your example, braces, which I have as a four-level-deep dependency, without any success. npm audit reports it as having the path cpx > chokidar > anymatch > micromatch > braces and I've specifically installed the latest version of all of those packages:

  "devDependencies": {
    "anymatch": "^3.1.1",
    "braces": "^3.0.2",
    "chokidar": "^3.3.1",
    "cpx": "^1.5.0",
    "micromatch": "^4.0.2"
  }

Even so, npm audit continues to report the vulnerability. I've deleted node_modules and package-lock.json and run npm install again, but it still doesn't resolve the issue. Is there something else that I need to do? I'm pretty much at my wits' end at this point.

Thread Thread
 
scottdotjs profile image
Scott Martin 🛠️

Typically, I found a workaround after writing the above. It turns out that cpx is unmaintained. There's a fork called cpx2 that works as a drop-in replacement and resolves the vulnerability. Would the solution to this problem otherwise have been to get cpx to update its dependencies, though?

Collapse
 
rewkie profile image
Chad Collins

I'm not getting the fix to display when running npm audit. Here is my entire output after running npm audit. Any help is appreciated and thank you for the article.

                   === npm audit security report ===                        

┌──────────────────────────────────────────────────────────────────────────────┐
│ Manual Review │
│ Some vulnerabilities require your attention to resolve │
│ │
│ Visit go.npm.me/audit-guide for additional guidance │
└──────────────────────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Low │ Incorrect Handling of Non-Boolean Comparisons During │
│ │ Minification │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package │ uglify-js │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in │ >= 2.4.24 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ jade │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path │ jade > transformers > uglify-js │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info │ npmjs.com/advisories/39
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Low │ Regular Expression Denial of Service │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package │ uglify-js │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in │ >=2.6.0 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ jade │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path │ jade > transformers > uglify-js │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info │ npmjs.com/advisories/48
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Critical │ Sandbox Bypass Leading to Arbitrary Code Execution │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package │ constantinople │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in │ >=3.1.1 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ jade │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path │ jade > constantinople │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info │ npmjs.com/advisories/568
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Low │ Regular Expression Denial of Service │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package │ clean-css │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in │ >=4.1.11 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ jade │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path │ jade > clean-css │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info │ npmjs.com/advisories/785
└───────────────┴──────────────────────────────────────────────────────────────┘
found 4 vulnerabilities (3 low, 1 critical) in 2463 scanned packages
4 vulnerabilities require manual review. See the full report for details.

Collapse
 
bsastregx profile image
bsastregx

Thanks!!

"The only difference is that manually upgrading our packages will allow us to upgrade a single package, test for a breaking change"

  1. Then what do we do if we find a breaking change? How do we fix it?
Collapse
 
bbenefield89 profile image
Brandon Benefield

@bsastregx If you run into a breaking change after upgrading a package then I would suggest you try and figure out what is causing breaking change. It could be as simple as the argument(s) to a method have changed or a simple environment variable needs to be set. If you can't figure out the issue then my suggestion is to either:

  • Choose a different package and remove the vulnerable package
  • Revert back to the vulnerable package (at your own risk)
Collapse
 
mnf profile image
Michael Freidgeim • Edited

Is it ok to ignore vulnerabilities in dev dependencies? In your particular example jest is used for tests, how the vulnerabilities in jest could cause the risks in production site? Should we spend time to fix vulnerabilities in dev packages?

Collapse
 
waligorar profile image
waligorar

Is there an option to ignore the vulnerabilities.

Collapse
 
bbenefield89 profile image
Brandon Benefield

There is an option to ignore vulnerabilities and that's the --no-audit flag when installing packages. I would like to say that I wouldn't recommend this at all but if your use case permits it then do what you will. If you don't mind, I'm interested in knowing why you would like to ignore the vulnerabilities?

Turning off npm audit on package installation

To turn off npm audit when installing a single package, use the --no-audit flag:

npm install example-package-name --no-audit

Collapse
 
waligorar profile image
waligorar

I work on a large team and this is handled by the frontend development team. My team works on backend development. So, I want to install the frontend with defects and all, so I can work on my back end development. The frontend team will work to fix their code, but why should I be blocked? Does that make sense?

Thread Thread
 
bbenefield89 profile image
Brandon Benefield

Yup, this definitely makes sense but I do want to point out that having vulnerabilities in your packages does not prevent you from working. NPM is just providing the warnings to you so that you are aware of the problems.

I can also see, in your situation, why you would want to prevent the messages. If it's not your place to fix it then why even bother with the messages, right?

Thanks for sharing.

Collapse
 
ankitjnv66 profile image
ankit singh

Hi Brandon,

with #npm audit command i am getting below response related to vulnerability.

Low Regular Expression Denial of Service in clean-css

Package clean-css

Patched in >=4.1.11

Dependency of gulp-minify-css [dev]

Path gulp-minify-css > clean-css

More info nodesecurity.io/advisories/1006346

Is there any way to get only severity level and Package detail?

Thanks in advance.

Collapse
 
bsastregx profile image
bsastregx

Algo, running npm audit does not show me the suggested command to update. Please, see image : imgur.com/mhnHoq4

Collapse
 
bbenefield89 profile image
Brandon Benefield

@bsastregx I believe the command is there but you may have glossed over it. Perhaps, you could leave the entire result of npm audit as a reply to this?

Collapse
 
billwright profile image
Bill Wright

Hi Brandon,

I have this same problem (no command to fix things). Using the --force doesn't fix things either. I tried to post my complete output but got an error saying there was a problem with my post, but no other information. I'm running npm version 6.4.1. At the end of my output I get this message: "See the full report for details." But where would I find the full report? There is no mention of where this report is.

Also, my problem is generally with grunt-* modules that use a vulnerable version of lodash. But I have the latest version of the grunt-modules. In that case, is there nothing that can be done? Short of not using the grunt-modules?

Thanks,
Bill

Collapse
 
ianbromwich profile image
Ian B

Very handy, thank you.

Collapse
 
jcubic profile image
Jakub T. Jankiewicz

Any hints how to update dependency of a dependency for vulnerability found by GitHub that is not listed by NPM?

Collapse
 
salothom profile image
Sarah Thompson

Is there a certain NPM or Node version requirement for the audit?

Some comments may only be visible to logged-in visitors. Sign in to view all comments.