13

Overview

I am having trouble resolving a ReDoS vulnerability identified by npm audit. My application has a nested sub-dependency ansi-html that is vulnerable to attack, but unfortunately, it seems that the maintainers have gone AWOL. As you can see in the comments section of that Github issue, to get around this problem, the community has made a fork of the repo called ansi-html-community located here, which addresses this vulnerability.

Thus, I would like to replace all nested references of ansi-html with ansi-html-community.

Problem

My normal strategy of using npm-force-resolutions does not seem to be able to override nested sub-dependencies with a different package altogether but rather only the same packages that are a different version number. I have researched this for several hours, but unfortunately, the only way I have found to fix this would appear to be with yarn, which I am now seriously considering using instead of npm. However, this is not ideal as our entire CI/CD pipeline is configured to use npm.

Does anyone know of any other way to accomplish nested sub-dependency package substitution/resolution without having to switch over to using yarn?

Related Questions

These are questions of interest that I was able to find, but unfortunately, they tend to only discuss methods to override package version number, not the package itself.

Discusses how to override version number:

How do I override nested NPM dependency versions?

Has a comment discussion about npm shrinkwrap (not ideal):

npm - how to override a dependent package's dependencies?

Justin Dehorty
  • 1,383
  • 1
  • 15
  • 26

2 Answers2

22

I figured it out. As of October 2021, the solution using npm-force-resolutions is actually very similar to how you would specify it using yarn. You just need to provide a link to the tarball where you would normally specify the overriding version number. Your resolutions section of package.json should look like this:

"resolutions": {
    "ansi-html": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz"
}

To find the link to the tarball, use the following command, modifying your registry as necessary:

npm view ansi-html-community dist.tarball --registry=https://registry.npmjs.org/

Also, note that for npm-force-resolutions to work when you run npm install, you will need a preinstall entry under the scripts section of package.json:

  "scripts": {
    "preinstall": "npx npm-force-resolutions"
  }
Justin Dehorty
  • 1,383
  • 1
  • 15
  • 26
  • 1
    It seems like this doesn't seem to work for me. npm ls ansi-html still returns the regular ansi-html@0.0.7 version. Do you just use the standard preinstall script? – Felix Oct 23 '21 at 09:07
  • 2
    This doesn't necessarily mean that it didn't work. As long as your `ansi-html` is ultimately getting resolved to `ansi-html-community` you should be good. If you haven't already try deleting your package-lock.json and regenerating it. Then search for instances of `ansi-html` and verify what it is getting resolved to. – Justin Dehorty Oct 25 '21 at 21:27
  • 3
    Running `npm-force-resolutions` as a `preinstall` `script` (via stackoverflow.com/a/68095189/132735) didn't yield the awaited results (having the `tarball` as the `resolved` entry). Running it manually instead (`npx npm-force-resolutions`) and then, of course, pushing the `lockfile` did the trick. Or one can just move to the latest yarn where native selective resolutions support exists. Apparently npm is also cooking an `overrides` feature -- https://github.com/npm/rfcs/blob/main/accepted/0036-overrides.md :> – Dr1Ku Nov 12 '21 at 14:00
  • But required package is not installed inside node_module. it jst updates the package-lock.json file. – Varun Jain Nov 30 '21 at 10:24
  • It will do both. The idea is once you are in a CI environment you can simply use `npm ci` at which point `node_modules` will be made directly from your `package-lock.json` (and nothing else). However, when you run `npm install` locally, it will update both your `node_modules` and your `package-lock.json` (assuming you have set up your `preinstall` in the `scripts` section of your `package.json` as shown at the end of my post). If this is not happening for you for some reason, consider completely deleting your `node_modules` and `package-lock.json` first and then trying again. – Justin Dehorty Nov 30 '21 at 22:42
-1

For those, who needs the same solution with yarn, just add this to your package.json

 "resolutions": {
    "ansi-html": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz"
  }

and then run yarn install

you might also do after this, if it won't work immediately

rm yarn.lock

yarn install

Val Neekman
  • 17,692
  • 14
  • 63
  • 66
yavnelf
  • 169
  • 1
  • 2
  • 12