Fixing NPM Dependencies Vulnerabilities
Tags: node, npm, tutorial, beginners
Published: 2019-06-13 02:23:29

## 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

```nim
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ 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

```nim
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`.

```nim
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

```nim
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.

```nim
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.