VYPR
Low severityNVD Advisory· Published Jun 23, 2023· Updated Dec 5, 2024

Shescape potential environment variable exposure on Windows with CMD

CVE-2023-35931

Description

Shescape is a simple shell escape library for JavaScript. An attacker may be able to get read-only access to environment variables. This bug has been patched in version 1.7.1.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
shescapenpm
< 1.7.11.7.1

Affected products

1

Patches

1
d0fce70f987a

Test coverage for environment variables (#982)

https://github.com/ericcornelissen/shescapeEric CornelissenJun 21, 2023via ghsa
5 files changed · +61 3
  • CHANGELOG.md+3 0 modified
    @@ -7,7 +7,9 @@ Versioning].
     
     ## [Unreleased]
     
    +- Add `%` escaping for CMD. ([#982])
     - Correct documented behavior of quoting functions. ([#969])
    +- Expand injection strings to cover environment variables. ([#982])
     
     ## [1.7.0] - 2023-06-12
     
    @@ -260,6 +262,7 @@ Versioning].
     [#909]: https://github.com/ericcornelissen/shescape/pull/909
     [#936]: https://github.com/ericcornelissen/shescape/pull/936
     [#969]: https://github.com/ericcornelissen/shescape/pull/969
    +[#982]: https://github.com/ericcornelissen/shescape/pull/982
     [552e8ea]: https://github.com/ericcornelissen/shescape/commit/552e8eab56861720b1d4e5474fb65741643358f9
     [keep a changelog]: https://keepachangelog.com/en/1.0.0/
     [semantic versioning]: https://semver.org/spec/v2.0.0.html
    
  • src/win/cmd.js+2 1 modified
    @@ -14,7 +14,7 @@ function escapeArgForInterpolation(arg) {
         .replace(/[\0\u0008\u001B\u009B]/gu, "")
         .replace(/\r?\n|\r/gu, " ")
         .replace(/\^/gu, "^^")
    -    .replace(/(["&<>|])/gu, "^$1");
    +    .replace(/(["%&<>|])/gu, "^$1");
     }
     
     /**
    @@ -53,6 +53,7 @@ function escapeArgForQuoted(arg) {
       return arg
         .replace(/[\0\u0008\u001B\u009B]/gu, "")
         .replace(/\r?\n|\r/gu, " ")
    +    .replace(/%/gu, "^%")
         .replace(/"/gu, `""`);
     }
     
    
  • test/fixtures/win.js+40 0 modified
    @@ -854,6 +854,16 @@ export const escape = {
             expected: { interpolation: "a$b$c", noInterpolation: "a$b$c" },
           },
         ],
    +    "percentage signs ('%')": [
    +      {
    +        input: "a%b",
    +        expected: { interpolation: "a^%b", noInterpolation: "a%b" },
    +      },
    +      {
    +        input: "a%b%c",
    +        expected: { interpolation: "a^%b^%c", noInterpolation: "a%b%c" },
    +      },
    +    ],
         "ampersands ('&')": [
           {
             input: "a&b",
    @@ -2010,6 +2020,16 @@ export const escape = {
             expected: { interpolation: "a`$b`$c", noInterpolation: "a`$b`$c" },
           },
         ],
    +    "percentage signs ('%')": [
    +      {
    +        input: "a%b",
    +        expected: { interpolation: "a%b", noInterpolation: "a%b" },
    +      },
    +      {
    +        input: "a%b%c",
    +        expected: { interpolation: "a%b%c", noInterpolation: "a%b%c" },
    +      },
    +    ],
         "ampersands ('&')": [
           {
             input: "a&b",
    @@ -2949,6 +2969,16 @@ export const quote = {
             expected: '"a$b$c"',
           },
         ],
    +    "percentage signs ('%')": [
    +      {
    +        input: "a%b",
    +        expected: '"a^%b"',
    +      },
    +      {
    +        input: "a%b%c",
    +        expected: '"a^%b^%c"',
    +      },
    +    ],
         "left double quotation mark ('“')": [
           {
             input: "a“b",
    @@ -3147,6 +3177,16 @@ export const quote = {
             expected: '"a`$b`$c"',
           },
         ],
    +    "percentage signs ('%')": [
    +      {
    +        input: "a%b",
    +        expected: '"a%b"',
    +      },
    +      {
    +        input: "a%b%c",
    +        expected: '"a%b%c"',
    +      },
    +    ],
         "left double quotation mark ('“')": [
           {
             input: "a“b",
    
  • test/fuzz/_common.cjs+7 1 modified
    @@ -49,11 +49,12 @@ function isShellPowerShell(shell) {
      *
      * @param {object} args The function arguments.
      * @param {string} args.arg The input argument that was echoed.
    + * @param {boolean} args.quoted Was `arg` quoted prior to echoing.
      * @param {string} args.shell The shell used for echoing.
      * @param {boolean} normalizeWhitespace Whether whitespace should be normalized.
      * @returns {string} The expected echoed value.
      */
    -function getExpectedOutput({ arg, shell }, normalizeWhitespace) {
    +function getExpectedOutput({ arg, quoted, shell }, normalizeWhitespace) {
       // Remove control characters, like Shescape
       arg = arg.replace(/[\0\u0008\u001B\u009B]/gu, "");
     
    @@ -64,6 +65,11 @@ function getExpectedOutput({ arg, shell }, normalizeWhitespace) {
         arg = arg.replace(/\r(?!\n)/gu, "");
       }
     
    +  // Adjust % for shell when quoted
    +  if (isShellCmd(shell) && quoted) {
    +    arg = arg.replace(/%/gu, "^%");
    +  }
    +
       if (normalizeWhitespace) {
         // Replace newline characters, like Shescape
         if (!isShellCmd(shell)) {
    
  • testing.js+9 1 modified
    @@ -15,7 +15,15 @@ import { checkedToString, toArrayIfNecessary } from "./src/reflection.js";
      *   assert.equal(result, "no injection");
      * }
      */
    -export const injectionStrings = ["\x00world", "&& ls", "'; ls #", '"; ls #'];
    +export const injectionStrings = [
    +  "\x00world",
    +  "&& ls",
    +  "'; ls #",
    +  '"; ls #',
    +  "$PATH",
    +  "$Env:PATH",
    +  "%PATH%",
    +];
     
     /**
      * A test stub of shescape that has the same input-output profile as the real
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.