CVE-2022-25918 (JavaScript, published 2022-10-27T10:15Z)
Description: value: The package shescape from 1.5.10 and before 1.6.1 are vulnerable to Regular Expression Denial of Service (ReDoS) via the escape function in index.js, due to the usage of insecure regex in the escapeArgBash function.
Severity: nan (CVSS v3 base score: 7.5)
Weakness: CWE-1333 \u2014 Inefficient Regular Expression Complexity
The product uses a regular expression with an inefficient, possibly exponential worst-case computational complexity that consumes excessive CPU cycles.
Repository: https://github.com/ericcornelissen/shescape
Files changed:
SECURITY.md
src/unix.js
test/fixtures/unix.js
test/unit/unix/escape.test.js
Commit message: Merge pull request from GHSA-cr84-xvw4-qx3c

* Test polynomial backtracking ReDoS attack string on Bash

Create a unit test for a (new) ReDoS string on bash. This test should be
failing in this commit.

* Fix ReDoS (as seen in ReDoS test 1) for bash

Update bash escaping to pessimistically escape opening curly braces,
similar to Zsh escaping, to fix the ReDoS due to the complex regular
expression for opening curly braces.

Update tests accordingly.

* Test against old ReDoS values and all shells

Refactor the ReDoS test such that 1) it's tested against all (supported)
shells, and 2) extensible to test against multiple potential ReDoS
strings. Regarding the latter, the scope has been updated to include
known ReDoS strings related to CVE-2022-36064.

The `redos` value is intentionally a function as this avoids building
the string unnecessarily if the file is imported but the `redos` value
isn't used.

* Update SECURITY.md

Add latest advisory and credit its finder

Vulnerable code:
| ID               | Date       | Affected versions | Patched versions |
| :--------------- | :--------- | :---------------- | :--------------- |
| `CVE-2021-21384` | 2021-03-19 | `<1.1.3`          | `1.1.3`          |
| `CVE-2022-24725` | 2022-03-03 | `>=1.4.0 <1.5.1`  | `1.5.1`          |
| `CVE-2022-31179` | 2022-07-26 | `<1.5.8`          | `1.5.8`          |
| `CVE-2022-31180` | 2022-07-26 | `>=1.4.0 <1.5.8`  | `1.5.8`          |
| `CVE-2022-36064` | 2022-08-29 | `>=1.5.1 <1.5.10` | `1.5.10`         |
- _None yet_
      .replace(/(["$&'()*;<>?`|])/gu, "\\$1")
      .replace(/(?<!\{)\{+(?=(?:[^{][^,.]*)?[,.][^}]*\})/gu, (curlyBraces) =>
        curlyBraces.replace(/\{/gu, "\\{")
      )
        expected: { interpolation: "a{b", noInterpolation: "a{b" },
        expected: { interpolation: "a{b{c", noInterpolation: "a{b{c" },
        expected: { interpolation: "a{b}c", noInterpolation: "a{b}c" },

Fixed code:
| ID                    | Date       | Affected versions | Patched versions |
| :-------------------- | :--------- | :---------------- | :--------------- |
| `CVE-2021-21384`      | 2021-03-19 | `<1.1.3`          | `1.1.3`          |
| `CVE-2022-24725`      | 2022-03-03 | `>=1.4.0 <1.5.1`  | `1.5.1`          |
| `CVE-2022-31179`      | 2022-07-26 | `<1.5.8`          | `1.5.8`          |
| `CVE-2022-31180`      | 2022-07-26 | `>=1.4.0 <1.5.8`  | `1.5.8`          |
| `CVE-2022-36064`      | 2022-08-29 | `>=1.5.1 <1.5.10` | `1.5.10`         |
| `GHSA-cr84-xvw4-qx3c` | 2022-10-25 | `>=1.5.10 <1.6.1` | `1.6.1`          |
- Elliot Ward ([@mowzk]) from [Snyk]
[@mowzk]: https://github.com/mowzk
[snyk]: https://snyk.io/
      .replace(/(["$&'()*;<>?`{|])/gu, "\\$1")
        expected: { interpolation: "a\\{b", noInterpolation: "a{b" },
        expected: { interpolation: "a\\{b\\{c", noInterpolation: "a{b{c" },
        expected: { interpolation: "a\\{b}c", noInterpolation: "a{b}c" },

export const redos = () => [
  // CVE-2022-36064
  `foo${"{".repeat(150_000)}bar`,
  `=${":".repeat(150_000)}foobar`,
  `{${",".repeat(150_000)}`,

  // No identifier (yet)
  "{,".repeat(150_000),
];
fixtures.redos().forEach((s, i) => {
  test(`bash, ReDoS #${i}`, (t) => {
    const escape = unix.getEscapeFunction("bash");
    escape(s, true, false);
    t.pass();
  });

  test(`dash, ReDoS #${i}`, (t) => {
    const escape = unix.getEscapeFunction("dash");
    escape(s, true, false);
    t.pass();
  });

  test(`zsh, ReDoS #${i}`, (t) => {
    const escape = unix.getEscapeFunction("zsh");
    escape(s, true, false);
    t.pass();
  });
});