So you have a node.js project in which npm audit tells you there is a dependency of a dependency that needs to be updated, but doing a simple npm audit fix won't do the trick, and for some reason, you cannot just bump the first-level package version and npm install to update it, because the second-level dependency package has no new version, so it won't try to resolve the new version of the third-level (dependency) package.

Sounds familiar?

Well, it seems familiar to me at least, because this week, I had to make sure our dependencies have no vulnerabilities, and I had this exact problem:

package-1@^0.3.0
  depends on:
    package-2@^3.0.1 (which is not vulnerable in itself, but has no new version available)
      depends on:
        package-3@^4.3.2 (which is vulnerable, so it needs to be updated)

So I couldn't just bump the package-1 version in the package.json then npm install or yarn install for it and also package-3 to be updated to safer versions. Because since package-2 had no new version, it wouldn't even bother to try and update its own dependencies.

That's when shrinkwrap comes to the rescue

The npm shrinkwrap command will create a npm-shrinkwrap.json file alongside your package.json, where you can specify package-3's desired version by doing so:

{
  "dependencies": {
    "package-1": {
      "version": "0.3.0",
      "from": "package-1@^0.3.0",
      "dependencies": {
        "package-2": {
          "version": "3.0.1",
          "from": "package-2@^3.0.1",
          "dependencies": {
            "package-3": {
              "version": "4.4.0",
              "from": "package-3@^4.4.0"
            }
          }
        }
      }
    }
  }
}

See that 4.4.0? That's the version that fixes the vulnerability.

Yarn also has that kind of trick, but it's cleaner (IMHO)

Yarn also has a feature that lets you specify the version that you want for our hypothetical package-3 example package.

Simply put, all you have to do is to add a "resolutions" object property inside your package.json, and set the version like so:

{
  ...
  "resolutions": {
    "package-1/**/package-3": "^4.4.0"
  }
}

... where 4.4.0 and later minor versions are fixing the vulnerability you want to squish.