At my place of work we have some private NPM packages that we maintain. Packages like ui-scaffolding. I'm running into a weird issue where when I use ui-scaffolding in two different front-end repos and run npm i && npm audit I get wildly different results between the two. And to make matters worse, I don't have a clean way to fix the problem.

In ProjectA I get found 0 vulnerabilities.

In ProjectB  I get the following:


....................
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High          │ Prototype Pollution                                          │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ lodash                                                       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ @private/ui-scaffolding                                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ @private/ui-scaffolding > karma-webpack > lodash                │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://npmjs.com/advisories/1065                            │
└───────────────┴──────────────────────────────────────────────────────────────┘


┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High          │ Prototype Pollution                                          │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ lodash                                                       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ @private/ui-scaffolding                                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ @private/ui-scaffolding > react2angular > ngcomponent > lodash  │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://npmjs.com/advisories/1065                            │
└───────────────┴──────────────────────────────────────────────────────────────┘


┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High          │ Prototype Pollution                                          │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ lodash                                                       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ @private/ui-scaffolding                                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ @private/ui-scaffolding > webpack-dev-server >                  │
│               │ http-proxy-middleware > lodash                               │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://npmjs.com/advisories/1065                            │
└───────────────┴──────────────────────────────────────────────────────────────┘


found 239 vulnerabilities (1 moderate, 238 high) in 42756 scanned packages

All of the 239 vulnerabilities are found as dependencies of ui-scaffolding and all of the vulnerabilities are related to lodash not being updated to version 4.17.12 or later.

So how is it possible that I get different versions of ui-scaffolding's dependencies when the ui-scaffolding version is identical? 🤔

My only guess is that...

  1. Those dependencies are all using ^versions of their dependencies
  2. AND ProjectA includes a dependency which uses the updated/fixed version of lodash.

👆If I'm wrong on this and you know why, please let me know in the comments.

So how do I fix this?

One way to fix it would be to work my way down the dependency tree and try and upgrade all of the dependencies that would result in lodash being updated. This just doesn't seem doable for the following reasons:

  1. In some cases it's just a matter of dependencies I use haven't been updated yet but eventually will. I don't have time to wait for these.
  2. In some cases I may need to open up PRs to have these versions updated. Again, I can't commit the time to this when I have my own deadlines.
  3. The library may have been fixed/updated ^15.5.0 but I'm using a very old version 10.3.0 and to get the updated dependency I'd have to refactor my own code and deal with loads of breaking changes.
  4. In some cases dependencies are no longer being maintained. This would mean I would have to fork the repo and maintain my own version.

So then how?

My first thought is that if I update ui-scaffolding to have a direct dependency on lodash@4.17.12 then it'll force UP all of the downstream's dependencies on it. So I'll wind up with lodash@4.17.12.

But something about this feels wrong. If this pattern continues, the package.json is going to get cluttered with dependencies that it doesn't directly need, only for the purpose of making sure the downstream dependencies are up to a set version.

This wouldn't be the worst thing in the world if I could do something like:

"dependencies": {
    "@babel/core": "7.0.0-beta.50",
    "@babel/preset-env": "7.0.0-beta.50",
    /** EVERYTHING BELOW HERE EXISTS BECAUSE OF... **
    "lodash": "4.17.12",
  },

But unfortunately you can't add comments to your JSON file and even if I could, npm i will reorganize the dependencies in alphabetical order.

So.. basically the "forced upgrade dependencies" are going to be sprinkled throughout the dependencies object, and I'm not sure there's anything I can do about it.

If you know how to better deal with this problem, I'd love to hear about it!

Ok.. after all this, I realized that the problem of 1 project works, one doesn't that really all I needed to do was delete the package-lock.json file in the failing web repo and rerun npm i would actually result in found 0 vulnerabilities. How does this work.. No idea. Previously changing node modules in the package.json file and running npm i always generated a new lock file. So I'm clueless as to why this wasn't working as expected. I hope to revisit this Monday when I'm back in the office and try and get to the bottom of what was going on, and I'll update this page accordingly. Because right now it'll just confuse people.

I also need to look into https://www.npmjs.com/package/npm-audit-ci-wrapper