Comparing version 1.5.5 to 1.5.6
@@ -12,2 +12,8 @@ # Changelog | ||
## [1.5.6] - 2022-07-02 | ||
- Fix unnecessary escaping of quotes with the `child_process` functions `fork`, | ||
`spawn`, and `execFile`. ([#310]) | ||
- Improve performance of escaping for Dash. ([#272]) | ||
## [1.5.5] - 2022-06-05 | ||
@@ -137,4 +143,6 @@ | ||
[#199]: https://github.com/ericcornelissen/shescape/pull/199 | ||
[#272]: https://github.com/ericcornelissen/shescape/pull/272 | ||
[#277]: https://github.com/ericcornelissen/shescape/pull/277 | ||
[#310]: https://github.com/ericcornelissen/shescape/pull/310 | ||
[keep a changelog]: https://keepachangelog.com/en/1.0.0/ | ||
[semantic versioning]: https://semver.org/spec/v2.0.0.html |
/** | ||
* @overview Contains TypeScript type definitions for Shescape. | ||
* @license MPL-2.0 | ||
* @author Eric Cornelissen <ericornelissen@gmail.com> | ||
*/ | ||
@@ -6,0 +5,0 @@ |
@@ -11,3 +11,3 @@ /** | ||
* @module shescape | ||
* @version 1.5.5 | ||
* @version 1.5.6 | ||
* @license MPL-2.0 | ||
@@ -14,0 +14,0 @@ */ |
{ | ||
"name": "shescape", | ||
"version": "1.5.5", | ||
"version": "1.5.6", | ||
"description": "simple shell escape library", | ||
@@ -22,7 +22,8 @@ "homepage": "https://ericcornelissen.github.io/shescape/", | ||
"coverage:e2e": "npm run _coverage -- --reports-dir=_reports/coverage/e2e npm run test:e2e", | ||
"coverage:integration": "npm run _coverage -- --reports-dir=_reports/coverage/integration npm run test:integration", | ||
"coverage:property": "npm run _coverage -- --reports-dir=_reports/coverage/property npm run test:property", | ||
"coverage:unit": "npm run _coverage -- --reports-dir=_reports/coverage/unit npm run test:unit", | ||
"format": "npm run _prettier -- --write", | ||
"prefuzz": "npm run transpile && node script/prefuzz.js", | ||
"fuzz": "jsfuzz ./test/fuzz/index.test.cjs ./.corpus", | ||
"prefuzz": "npm run transpile", | ||
"fuzz": "node script/fuzz.js", | ||
"lint": "npm run _prettier -- --check", | ||
@@ -33,7 +34,9 @@ "prepare": "is-ci || husky install script/hooks", | ||
"test:compatibility": "mocha test/compat/**/*.test.{js,cjs}", | ||
"test:e2e": "ava test/e2e/**/*.test.{js,cjs}", | ||
"test:e2e": "ava test/e2e/**/*.test.js", | ||
"test:integration": "ava test/integration/**/*.test.{js,cjs}", | ||
"test:mutation": "stryker run stryker.config.json", | ||
"test:property": "ava test/prop/**/*.test.js", | ||
"test:unit": "ava test/unit/**/*.test.js", | ||
"transpile": "rollup -c" | ||
"transpile": "rollup -c", | ||
"vet": "depcheck && unimported" | ||
}, | ||
@@ -61,9 +64,10 @@ "repository": { | ||
"devDependencies": { | ||
"@stryker-mutator/core": "6.0.1", | ||
"@stryker-mutator/core": "6.1.2", | ||
"ava": "4.3.0", | ||
"ava-fast-check": "5.0.0", | ||
"ava-fast-check": "6.0.0", | ||
"benchmark": "2.1.4", | ||
"c8": "7.11.3", | ||
"depcheck": "1.4.3", | ||
"dotenv": "16.0.1", | ||
"fast-check": "2.25.0", | ||
"fast-check": "3.0.1", | ||
"husky": "8.0.1", | ||
@@ -73,5 +77,6 @@ "is-ci": "3.0.1", | ||
"mocha": "9.2.2", | ||
"prettier": "2.6.2", | ||
"prettier": "2.7.1", | ||
"rollup": "2.75.3", | ||
"sinon": "14.0.0" | ||
"sinon": "14.0.0", | ||
"unimported": "1.21.0" | ||
}, | ||
@@ -78,0 +83,0 @@ "engines": { |
@@ -47,66 +47,2 @@ # Shescape | ||
### Recipes | ||
When using `fork`, `spawn`, `execFile`, or similar, **without configuration** it | ||
is recommended to use the [escapeAll()](#escapeallargs) function to escape the | ||
array of arguments. This is because these function come with built-in protection | ||
which may cause unexpected behaviour when using [quoteAll()](#quoteallargs). | ||
```js | ||
import { spawn } from "child_process"; | ||
import * as shescape from "shescape"; | ||
const name = "&& ls"; | ||
const echo = spawn("echo", shescape.escapeAll(["Hello", name])); | ||
echo.stdout.on("data", (data) => { | ||
console.log(data.toString()); | ||
// Output: "Hello && ls" | ||
}); | ||
``` | ||
When using `fork`, `spawn`, `execFile`, or similar, and set `{ shell: true }` in | ||
the call options it is recommended to use the [quoteAll()](#quoteallargs) | ||
function to quote and escape the array of arguments. | ||
```js | ||
import { spawn } from "child_process"; | ||
import * as shescape from "shescape"; | ||
const name = "&& ls"; | ||
const echo = spawn("echo", shescape.quoteAll(["Hello", name]), { shell: true }); | ||
echo.stdout.on("data", (data) => { | ||
console.log(data.toString()); | ||
// Output: "Hello && ls" | ||
}); | ||
``` | ||
When using the `exec` function, or similar, it is recommended to use the | ||
[quote()](#quotearg) function to quote and escape individual arguments. | ||
```js | ||
import { exec } from "child_process"; | ||
import * as shescape from "shescape"; | ||
const name = "&& ls"; | ||
exec(`echo Hello ${shescape.quote(name)}`, (err, stdout) => { | ||
console.log(stdout); | ||
// Output: "Hello && ls" | ||
}); | ||
``` | ||
When configuring what shell should be used when calling `exec`, `execFile`, or | ||
`spawn` make sure to pass that information to Shescape as well, for example: | ||
```js | ||
import { exec } from "child_process"; | ||
import * as shescape from "shescape"; | ||
const options = { shell: "/bin/bash" }; | ||
const name = "&& ls"; | ||
exec(`echo Hello ${shescape.quote(name, options)}`, options, (err, stdout) => { | ||
console.log(stdout); | ||
// Output: "Hello && ls" | ||
}); | ||
``` | ||
## Shells | ||
@@ -128,2 +64,6 @@ | ||
## Recipes | ||
View the [recipes] for examples of how to use Shescape. | ||
## API | ||
@@ -287,4 +227,5 @@ | ||
[license]: https://github.com/ericcornelissen/shescape/blob/main/LICENSE | ||
[recipes]: docs/recipes.md | ||
[security]: https://github.com/ericcornelissen/shescape/blob/main/SECURITY.md | ||
[shell injection]: https://portswigger.net/web-security/os-command-injection | ||
[source code]: https://github.com/ericcornelissen/shescape |
@@ -113,2 +113,3 @@ /** | ||
* @param {boolean} args.interpolation Is interpolation enabled. | ||
* @param {boolean} args.quoted Is `arg` being quoted. | ||
* @param {string} args.shellName The name of the shell to escape `arg` for. | ||
@@ -120,3 +121,6 @@ * @param {Object} deps The dependencies for this function. | ||
*/ | ||
function escape({ arg, interpolation, shellName }, { getEscapeFunction }) { | ||
function escape( | ||
{ arg, interpolation, quoted, shellName }, | ||
{ getEscapeFunction } | ||
) { | ||
if (!isStringable(arg)) { | ||
@@ -128,3 +132,3 @@ throw new TypeError(typeError); | ||
const escape = getEscapeFunction(shellName); | ||
const escapedArg = escape(argAsString, interpolation); | ||
const escapedArg = escape(argAsString, interpolation, quoted); | ||
return escapedArg; | ||
@@ -147,3 +151,3 @@ } | ||
const escapedArg = escape( | ||
{ arg, interpolation: false, shellName }, | ||
{ arg, interpolation: false, quoted: true, shellName }, | ||
{ getEscapeFunction } | ||
@@ -150,0 +154,0 @@ ); |
@@ -8,2 +8,3 @@ /** | ||
import * as path from "path"; | ||
import which from "which"; | ||
@@ -40,6 +41,7 @@ | ||
* @param {boolean} interpolation Is interpolation enabled. | ||
* @param {boolean} quoted Is `arg` being quoted. | ||
* @returns {string} The escaped argument. | ||
*/ | ||
function escapeArgBash(arg, interpolation) { | ||
let result = arg.replace(/\u{0}/gu, ""); | ||
function escapeArgBash(arg, interpolation, quoted) { | ||
let result = arg.replace(/\u0000/g, ""); | ||
@@ -50,3 +52,3 @@ if (interpolation) { | ||
.replace(/^(~|#)/g, "\\$1") | ||
.replace(/(\*|\?)/gu, "\\$1") | ||
.replace(/(\*|\?)/g, "\\$1") | ||
.replace(/(\$|\;|\&|\|)/g, "\\$1") | ||
@@ -57,3 +59,3 @@ .replace(/(\(|\)|\<|\>)/g, "\\$1") | ||
.replace(/(?<=\=(?:.*?:)?)(~)(?=\:|\=|\-|\+|\/|0|\s|$)/g, "\\$1"); | ||
} else { | ||
} else if (quoted) { | ||
result = result.replace(/'/g, `'\\''`); | ||
@@ -66,2 +68,29 @@ } | ||
/** | ||
* Escapes a shell argument for use in Dash | ||
* | ||
* @param {string} arg The argument to escape. | ||
* @param {boolean} interpolation Is interpolation enabled. | ||
* @param {boolean} quoted Is `arg` being quoted. | ||
* @returns {string} The escaped argument. | ||
*/ | ||
function escapeArgDash(arg, interpolation, quoted) { | ||
let result = arg.replace(/\u0000/g, ""); | ||
if (interpolation) { | ||
result = result | ||
.replace(/\\/g, "\\\\") | ||
.replace(/^(~|#)/g, "\\$1") | ||
.replace(/(\*|\?)/g, "\\$1") | ||
.replace(/(\$|\;|\&|\|)/g, "\\$1") | ||
.replace(/(\(|\)|\<|\>)/g, "\\$1") | ||
.replace(/("|'|`)/g, "\\$1") | ||
.replace(/\{(?=(.*?(?:\,|\.).*?)\})/g, "\\{"); | ||
} else if (quoted) { | ||
result = result.replace(/'/g, `'\\''`); | ||
} | ||
return result; | ||
} | ||
/** | ||
* Escapes a shell argument for use in Zsh. | ||
@@ -71,6 +100,7 @@ * | ||
* @param {boolean} interpolation Is interpolation enabled. | ||
* @param {boolean} quoted Is `arg` being quoted. | ||
* @returns {string} The escaped argument. | ||
*/ | ||
function escapeArgZsh(arg, interpolation) { | ||
let result = arg.replace(/\u{0}/gu, ""); | ||
function escapeArgZsh(arg, interpolation, quoted) { | ||
let result = arg.replace(/\u0000/g, ""); | ||
@@ -81,9 +111,9 @@ if (interpolation) { | ||
.replace(/^(~|#)/g, "\\$1") | ||
.replace(/(\*|\?)/gu, "\\$1") | ||
.replace(/(\*|\?)/g, "\\$1") | ||
.replace(/(\$|\;|\&|\|)/g, "\\$1") | ||
.replace(/(\(|\)|\<|\>)/g, "\\$1") | ||
.replace(/("|'|`)/g, "\\$1") | ||
.replace(/^=/gu, "\\=") | ||
.replace(/^=/g, "\\=") | ||
.replace(/(\[|\]|\{|\})/g, "\\$1"); | ||
} else { | ||
} else if (quoted) { | ||
result = result.replace(/'/g, `'\\''`); | ||
@@ -114,3 +144,3 @@ } | ||
[binBash, escapeArgBash], | ||
[binDash, escapeArgBash], | ||
[binDash, escapeArgDash], | ||
[binZsh, escapeArgZsh], | ||
@@ -117,0 +147,0 @@ ]); |
@@ -8,2 +8,3 @@ /** | ||
import * as path from "path"; | ||
import which from "which"; | ||
@@ -32,6 +33,7 @@ | ||
* @param {boolean} interpolation Is interpolation enabled. | ||
* @param {boolean} quoted Is `arg` being quoted. | ||
* @returns {string} The escaped argument. | ||
*/ | ||
function escapeArgCmd(arg, interpolation) { | ||
let result = arg.replace(/\u{0}/gu, ""); | ||
function escapeArgCmd(arg, interpolation, quoted) { | ||
let result = arg.replace(/\u0000/g, ""); | ||
@@ -44,3 +46,3 @@ if (interpolation) { | ||
.replace(/(\&|\|)/g, "^$1"); | ||
} else { | ||
} else if (quoted) { | ||
result = result.replace(/"/g, `""`); | ||
@@ -57,7 +59,8 @@ } | ||
* @param {boolean} interpolation Is interpolation enabled. | ||
* @param {boolean} quoted Is `arg` being quoted. | ||
* @returns {string} The escaped argument. | ||
*/ | ||
function escapeArgPowerShell(arg, interpolation) { | ||
function escapeArgPowerShell(arg, interpolation, quoted) { | ||
let result = arg | ||
.replace(/\u{0}/gu, "") | ||
.replace(/\u0000/g, "") | ||
.replace(/`/g, "``") | ||
@@ -74,3 +77,3 @@ .replace(/\$/g, "`$"); | ||
.replace(/("|“|”|„)/g, "`$1"); | ||
} else { | ||
} else if (quoted) { | ||
result = result.replace(/("|“|”|„)/g, "$1$1"); | ||
@@ -77,0 +80,0 @@ } |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
82750
1534
16
229