Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exponential ReDoS (CVE-2021-23424) #19

Closed
b-c-ds opened this issue May 7, 2021 · 22 comments · Fixed by #20 or gebhardtr/ansi-html#1
Closed

Exponential ReDoS (CVE-2021-23424) #19

b-c-ds opened this issue May 7, 2021 · 22 comments · Fixed by #20 or gebhardtr/ansi-html#1

Comments

@b-c-ds
Copy link

b-c-ds commented May 7, 2021

Posting here as unable to contact maintainer.

Doyensec Vulnerability Advisory

  • Regular Expression Denial of Service (ReDoS) in ansi-html
  • Affected Product: ansi-html <= 0.0.7
  • Vendor: https://github.com/Tjatse
  • Severity: Low
  • Vulnerability Class: Denial of Service
  • Status: Open
  • Author(s): Ben Caller (Doyensec)

SUMMARY

The npm package ansi-html uses a regular expression which is vulnerable to Regular Expression Denial of Service (ReDoS).
If an attacker provides a malicious string, ansi-html will get stuck processing the input for an extremely long time.

TECHNICAL DESCRIPTION

The vulnerable regular expression is

\033\[(\d+)*m

var ret = text.replace(/\033\[(\d+)*m/g, function (match, seq) {

Due to the (\d+)* part, this regular expression has catastrophic backtracking when given a long string of digits.

The behaviour occurs as long as the digits are not followed immediately by an 'm'.

The complexity is exponential: increasing the length of the malicious string by one makes processing take about twice as long.

REPRODUCTION STEPS

In nodejs, run:

require('ansi-html')('\x1b[0m\x1b[' + '0'.repeat(35))

Notice that node hangs at 100% CPU. Increasing the number of spaces increases the processing time.

On my laptop that would take three minutes to complete, whereas

require('ansi-html')('\x1b[0m\x1b[' + '0'.repeat(53))

would take just over one year to complete.

REMEDIATION

Remove the asterisk from the regular expression on line 62.

=

Doyensec (www.doyensec.com) is an independent security research and development company focused on vulnerability discovery and remediation. We work at the intersection of software development and offensive engineering to help companies craft secure code.

Copyright 2021 by Doyensec LLC. All rights reserved.

Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting
it, and that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided
that due credit is given. The information in the advisory is believed to be accurate at the time of publishing based on
currently available information, and it is provided as-is, as a free service to the community by Doyensec LLC. There are
no warranties with regard to this information, and Doyensec LLC does not accept any liability for any direct, indirect, or
consequential loss or damage arising from use of, or reliance on, this information.

@krishnaUIDev
Copy link

Looks like this package is not accepting new merge requests and not in maintenance ☹️

@SymbioticKilla
Copy link

@Tjatse @glenjamin @danfuzz Any chance to fix this issue?

@glenjamin
Copy link
Contributor

I am not a maintainer of this project.

@danfuzz
Copy link
Contributor

danfuzz commented Aug 23, 2021

Me neither; sorry!

@graniczny
Copy link

+1 any chance of fixing it @Tjatse ?

@b-c-ds b-c-ds changed the title Exponential ReDoS Exponential ReDoS (CVE-2021-23424) Aug 25, 2021
mahdyar added a commit to mahdyar/ansi-html-community that referenced this issue Sep 5, 2021
@mahdyar
Copy link

mahdyar commented Sep 5, 2021

Okay, I published the fixed version to npm. It's called ansi-html-community.
The repo: @mahdyar/ansi-html-community.

nttibbetts added a commit to nttibbetts/webpack-hot-middleware that referenced this issue Sep 9, 2021
This fixes the vulnerability reported in [CVE-2021-23424][CVE], by
replacing the ansi-html dependency with a fork of the project that has
the [suggested fix][ansi-html-fix] and resolves [webpack-contrib#412][412]

[CVE]: https://nvd.nist.gov/vuln/detail/CVE-2021-23424
[ansi-html-fix]: Tjatse/ansi-html#19
[412]: webpack-contrib#412
nttibbetts added a commit to nttibbetts/webpack-hot-middleware that referenced this issue Sep 9, 2021
This fixes the vulnerability reported in [CVE-2021-23424][CVE], by
replacing the ansi-html dependency with a fork of the project that has
the [suggested fix][ansi-html-fix] and resolves [webpack-contrib#412][412]

[CVE]: https://nvd.nist.gov/vuln/detail/CVE-2021-23424
[ansi-html-fix]: Tjatse/ansi-html#19
[412]: webpack-contrib#412
nttibbetts added a commit to nttibbetts/webpack-hot-middleware that referenced this issue Sep 9, 2021
This fixes the vulnerability reported in [CVE-2021-23424][CVE] by
replacing the ansi-html dependency with a fork of the project that has
the [suggested fix][ansi-html-fix] and resolves [webpack-contrib#412][412]

[CVE]: https://nvd.nist.gov/vuln/detail/CVE-2021-23424
[ansi-html-fix]: Tjatse/ansi-html#19
[412]: webpack-contrib#412
nttibbetts added a commit to nttibbetts/webpack-hot-middleware that referenced this issue Sep 9, 2021
This is a fix for the vulnerability reported in [CVE-2021-23424][CVE] by
replacing the ansi-html dependency with a fork of the project that has
the [suggested fix][ansi-html-fix] and resolves [webpack-contrib#412][412]

[CVE]: https://nvd.nist.gov/vuln/detail/CVE-2021-23424
[ansi-html-fix]: Tjatse/ansi-html#19
[412]: webpack-contrib#412
@CoryDanielson
Copy link

CoryDanielson commented Oct 6, 2021

ty @mahdyar

How to fix, if you're using yarn

If you're using yarn and this package is not a direct dependency of your repo, you can resolve this issue with Selective Dependency Resolutions

Install ansi-html-community

yarn add ansi-html-community@0.0.8

Add the resolution to your package.json

This instructs yarn to install ansi-html-community@0.0.8 instead of ansi-html.

"resolutions": {
  "ansi-html": "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41",
}

Confirmation

After removing and re-installing node_modules (rm -rf node_modules; yarn) you can confirm that your ansi-html dependency is actually ansi-html-community

❯ cat node_modules/ansi-html/package.json
{
  "name": "ansi-html-community",
  "version": "0.0.8",
  "description": "An elegant lib that converts the chalked (ANSI) text to HTML. (Community)",
  "main": "index.js",
  "scripts": {
    "test": "./node_modules/.bin/mocha -R spec -t 5000"
  },
  "bin": {
    "ansi-html": "./bin/ansi-html"
  },
  "repository": {
    "type": "git",
    "url": "git://github.com/mahdyar/ansi-html-community.git"
  },
/* ... truncated ... */

@cmacdonnacha
Copy link

ty @mahdyar

If you're using yarn and this package is not a direct dependency of your repo, you can resolve this issue with Selective Dependency Resolutions

Install ansi-html-community

yarn add ansi-html-community@0.0.8

Add the resolution to your package.json

This instructs yarn to install ansi-html-community@0.0.8 instead of ansi-html.

"resolutions": {
  "ansi-html": "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41",
}

Confirmation

After removing and re-installing node_modules (rm -rf node_modules; yarn) you can confirm that your ansi-html dependency is actually ansi-html-community

❯ cat node_modules/ansi-html/package.json
{
  "name": "ansi-html-community",
  "version": "0.0.8",
  "description": "An elegant lib that converts the chalked (ANSI) text to HTML. (Community)",
  "main": "index.js",
  "scripts": {
    "test": "./node_modules/.bin/mocha -R spec -t 5000"
  },
  "bin": {
    "ansi-html": "./bin/ansi-html"
  },
  "repository": {
    "type": "git",
    "url": "git://github.com/mahdyar/ansi-html-community.git"
  },
/* ... truncated ... */

Anyone know how to do this with npm-force-resolutions?

runska added a commit to navikt/forebygge-sykefravaer that referenced this issue Oct 7, 2021
@CoryDanielson
Copy link

@cmacdonnacha you may want to open an issue with npm-force-resolutions. I don't see anything in their docs for a resolution value that is not a version number.

@cmacdonnacha
Copy link

@cmacdonnacha you may want to open an issue with npm-force-resolutions. I don't see anything in their docs for a resolution value that is not a version number.

Thanks. It's actually CRA that uses this and they seem to have gone a but stale with releases so I think I will probably move to Vite.

@jdehorty
Copy link

jdehorty commented Oct 16, 2021

Anyone know how to do this with npm-force-resolutions?

@cmacdonnacha
As it turns out, yarn is not necessary. This is how you can do it using only npm-force-resolutions:

https://stackoverflow.com/questions/69548370/how-to-override-a-nested-npm-sub-dependency-with-a-different-package-altogether/69591894#69591894

@cmacdonnacha
Copy link

Anyone know how to do this with npm-force-resolutions?

@cmacdonnacha As it turns out, yarn is not necessary. This is how you can do it using only npm-force-resolutions:

https://stackoverflow.com/questions/69548370/how-to-override-a-nested-npm-sub-dependency-with-a-different-package-altogether/69591894#69591894

That worked for me, thanks so much @jdehorty

@ranka23
Copy link

ranka23 commented Oct 26, 2021

ty @mahdyar

How to fix, if you're using yarn

If you're using yarn and this package is not a direct dependency of your repo, you can resolve this issue with Selective Dependency Resolutions

Install ansi-html-community

yarn add ansi-html-community@0.0.8

Add the resolution to your package.json

This instructs yarn to install ansi-html-community@0.0.8 instead of ansi-html.

"resolutions": {
  "ansi-html": "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41",
}

Confirmation

After removing and re-installing node_modules (rm -rf node_modules; yarn) you can confirm that your ansi-html dependency is actually ansi-html-community

❯ cat node_modules/ansi-html/package.json
{
  "name": "ansi-html-community",
  "version": "0.0.8",
  "description": "An elegant lib that converts the chalked (ANSI) text to HTML. (Community)",
  "main": "index.js",
  "scripts": {
    "test": "./node_modules/.bin/mocha -R spec -t 5000"
  },
  "bin": {
    "ansi-html": "./bin/ansi-html"
  },
  "repository": {
    "type": "git",
    "url": "git://github.com/mahdyar/ansi-html-community.git"
  },
/* ... truncated ... */

This works. However, when I run yarn audit after making these changes, I receive this error:

An unexpected error occurred: "Unexpected audit response (Missing Metadata): false".

The project compiles and running this command cat node_modules/ansi-html/package.json gives the expected output of ansi-html being inferred as ansi-html-community. But, yarn audit fails with a 400 error response from npm.

Anyone facing this issue? Any solutions?

@ShanUSAC
Copy link

ty @mahdyar

How to fix, if you're using yarn

If you're using yarn and this package is not a direct dependency of your repo, you can resolve this issue with Selective Dependency Resolutions

Install ansi-html-community

yarn add ansi-html-community@0.0.8

Add the resolution to your package.json

This instructs yarn to install ansi-html-community@0.0.8 instead of ansi-html.

"resolutions": {
  "ansi-html": "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41",
}

Confirmation

After removing and re-installing node_modules (rm -rf node_modules; yarn) you can confirm that your ansi-html dependency is actually ansi-html-community

❯ cat node_modules/ansi-html/package.json
{
  "name": "ansi-html-community",
  "version": "0.0.8",
  "description": "An elegant lib that converts the chalked (ANSI) text to HTML. (Community)",
  "main": "index.js",
  "scripts": {
    "test": "./node_modules/.bin/mocha -R spec -t 5000"
  },
  "bin": {
    "ansi-html": "./bin/ansi-html"
  },
  "repository": {
    "type": "git",
    "url": "git://github.com/mahdyar/ansi-html-community.git"
  },
/* ... truncated ... */

Thanks @mahdyar . This fix works and npm install works fine. However when I do "npm audit fix", I am seeing the below error.

$ npm audit fix
npm ERR! Invalid Version: https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz

Could you check what's missing?

@ShanUSAC
Copy link

ty @mahdyar

How to fix, if you're using yarn

If you're using yarn and this package is not a direct dependency of your repo, you can resolve this issue with Selective Dependency Resolutions

Install ansi-html-community

yarn add ansi-html-community@0.0.8

Add the resolution to your package.json

This instructs yarn to install ansi-html-community@0.0.8 instead of ansi-html.

"resolutions": {
  "ansi-html": "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41",
}

Confirmation

After removing and re-installing node_modules (rm -rf node_modules; yarn) you can confirm that your ansi-html dependency is actually ansi-html-community

❯ cat node_modules/ansi-html/package.json
{
  "name": "ansi-html-community",
  "version": "0.0.8",
  "description": "An elegant lib that converts the chalked (ANSI) text to HTML. (Community)",
  "main": "index.js",
  "scripts": {
    "test": "./node_modules/.bin/mocha -R spec -t 5000"
  },
  "bin": {
    "ansi-html": "./bin/ansi-html"
  },
  "repository": {
    "type": "git",
    "url": "git://github.com/mahdyar/ansi-html-community.git"
  },
/* ... truncated ... */

Thanks @mahdyar . This fix works and npm install works fine. However when I do "npm audit fix", I am seeing the below error.

$ npm audit fix
npm ERR! Invalid Version: https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz

Could you check what's missing?

My resolutions:

"resolutions": {
"browserslist": "4.16.5",
"dns-packet": "5.2.2",
"glob-parent": "6.0.1",
"url-parse": "1.5.2",
"path-parse": "1.0.7",
"jszip": "3.7.0",
"ansi-html": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz"
},

@jdehorty
Copy link

@ShanUSAC are you trying to use yarn or npm?

If npm follow the directions outlined here:

https://stackoverflow.com/a/69591894/12649786

Note that you will also need a preinstall entry under scripts for that to work like this:

  "scripts": {
    "preinstall": "npx npm-force-resolutions",
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }

@kpeters-cbsi
Copy link

ty @mahdyar

How to fix, if you're using yarn

If you're using yarn and this package is not a direct dependency of your repo, you can resolve this issue with Selective Dependency Resolutions

Install ansi-html-community

yarn add ansi-html-community@0.0.8

Add the resolution to your package.json

This instructs yarn to install ansi-html-community@0.0.8 instead of ansi-html.

"resolutions": {
  "ansi-html": "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41",
}

Confirmation

After removing and re-installing node_modules (rm -rf node_modules; yarn) you can confirm that your ansi-html dependency is actually ansi-html-community

❯ cat node_modules/ansi-html/package.json
{
  "name": "ansi-html-community",
  "version": "0.0.8",
  "description": "An elegant lib that converts the chalked (ANSI) text to HTML. (Community)",
  "main": "index.js",
  "scripts": {
    "test": "./node_modules/.bin/mocha -R spec -t 5000"
  },
  "bin": {
    "ansi-html": "./bin/ansi-html"
  },
  "repository": {
    "type": "git",
    "url": "git://github.com/mahdyar/ansi-html-community.git"
  },
/* ... truncated ... */

I tried this with yarn in my project with two workspaces, frontend and backend. The ansi-html package is a dependency from something in the frontend workspace. I first tried adding the fix to frontend/package.json, but, while this produced no errors, cat frontend/node_modules/ansi-html/package.json still showed version 0.0.7. So I tried adding the fix to the root package.json, but after I did rm -rf node_modules frontend/node_modules backend/node_modules ; yarn I got:

➜  locust-self-service git:(fix-cve-2021-23424) ✗ rm -rf node_modules frontend/node_modules backend/node_modules ; yarn ; cat frontend/node_modules/ansi-html/package.json
➤ YN0000: ┌ Project validation
➤ YN0057: │ frontend: Resolutions field will be ignored
➤ YN0000: └ Completed
➤ YN0000: ┌ Resolution step
➤ YN0001: │ Error: ansi-html@https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41 isn't supported by any available resolver
    at Xc.getResolverByDescriptor (/Users/cpete0624/work/locust-self-service/.yarn/releases/yarn-3.0.2.cjs:294:5330)
    at Xc.bindDescriptor (/Users/cpete0624/work/locust-self-service/.yarn/releases/yarn-3.0.2.cjs:294:4719)
    at reduceDependency (/Users/cpete0624/work/locust-self-service/.yarn/releases/yarn-3.0.2.cjs:294:3379)
    at co.reduceHook (/Users/cpete0624/work/locust-self-service/.yarn/releases/yarn-3.0.2.cjs:295:3206)
    at p (/Users/cpete0624/work/locust-self-service/.yarn/releases/yarn-3.0.2.cjs:303:6768)
    at async Promise.all (index 65)
➤ YN0000: └ Completed
➤ YN0000: Failed with errors in 0s 192ms

@kdblocher
Copy link

If you are using yarn and ansi-html is only a transitive dependency, you shouldn't need to install it yourself. Just using

"resolutions": {
  "ansi-html": "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
}

should be enough.

@kpeters-cbsi
Copy link

If you are using yarn and ansi-html is only a transitive dependency, you shouldn't need to install it yourself. Just using

"resolutions": {
  "ansi-html": "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
}

should be enough.

Do I put that in my root package.json or in frontend/package.json?

@sauldeleon
Copy link

worked like a charm. Thanks a lot @mahdyar

@kdblocher
Copy link

kdblocher commented Nov 18, 2021 via email

DeeDeeG added a commit to DeeDeeG/refugerestrooms that referenced this issue Nov 28, 2021
Pin to an exact version, 0.0.8, which I have personally verified
only contains the desired change, plus package.json metadata changes
and updates to README.md.

(Pinning means we don't have to trust the independent GitHub user
who published the fork, just the content of the patch.)

One can do the following commands to download and inspect the contents
of the packages themselves, as hosted on the npm package registry...
- `npm pack ansi-html@0.0.7`
- `npm pack ansi-html-community@0.0.8`
Then extract the tarballs and compare the content.

See the following for details of the fork and why it was made:
- github[dot]com/Tjatse/ansi-html/issues/19
- github[dot]com/Tjatse/ansi-html/issues/19#issuecomment-913119841
@Yonet
Copy link

Yonet commented Feb 23, 2022

For those of you who are using npm:

How to fix, if you're using npm

Starting with npm 8.3, you can add an option to override your dependency of your dependencies by defining overrides on your root package.json.

  1. Override ansi-html with ansi-html-community in package.json
    "overrides": { "ansi-html": "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz" },
  2. Delete your package-lock.json and node modules folder
  3. npm install
    npm i

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet