Skip to content

Commit 08a67cb

Browse files
committed
fix(utils): quote shell arguments to prevent malicious injection
1 parent a72e87c commit 08a67cb

File tree

7 files changed

+33
-18
lines changed

7 files changed

+33
-18
lines changed

package-lock.json

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"parse-lcov": "^1.0.4",
3939
"rimraf": "^6.0.1",
4040
"semver": "^7.6.3",
41+
"shell-quote": "^1.8.3",
4142
"simple-git": "^3.26.0",
4243
"ts-morph": "^24.0.0",
4344
"tslib": "^2.6.2",
@@ -76,6 +77,7 @@
7677
"@types/node": "^22.13.4",
7778
"@types/react": "18.3.1",
7879
"@types/react-dom": "18.3.0",
80+
"@types/shell-quote": "^1.7.5",
7981
"@vitejs/plugin-react": "^5.0.0",
8082
"@vitest/coverage-v8": "1.3.1",
8183
"@vitest/eslint-plugin": "^1.1.38",

packages/plugin-coverage/src/lib/runner/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
createRunnerFiles,
88
ensureDirectoryExists,
99
executeProcess,
10-
filePathToCliArg,
1110
objectToCliArgs,
1211
readJsonFile,
1312
ui,
@@ -66,7 +65,7 @@ export async function createRunnerConfig(
6665
return {
6766
command: 'node',
6867
args: [
69-
filePathToCliArg(scriptPath),
68+
scriptPath,
7069
...objectToCliArgs({ runnerConfigPath, runnerOutputPath }),
7170
],
7271
configFile: runnerConfigPath,

packages/plugin-eslint/src/lib/runner/lint.ts

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
import type { ESLint, Linter } from 'eslint';
2-
import { platform } from 'node:os';
3-
import {
4-
distinct,
5-
executeProcess,
6-
filePathToCliArg,
7-
toArray,
8-
} from '@code-pushup/utils';
2+
import { distinct, executeProcess, toArray } from '@code-pushup/utils';
93
import type { ESLintTarget } from '../config.js';
104
import { setupESLint } from '../setup.js';
115
import type { LinterOutput, RuleOptionsPerFile } from './types.js';
@@ -29,14 +23,11 @@ async function executeLint({
2923
command: 'npx',
3024
args: [
3125
'eslint',
32-
...(eslintrc ? [`--config=${filePathToCliArg(eslintrc)}`] : []),
26+
...(eslintrc ? [`--config=${eslintrc}`] : []),
3327
...(typeof eslintrc === 'object' ? ['--no-eslintrc'] : []),
3428
'--no-error-on-unmatched-pattern',
3529
'--format=json',
36-
...toArray(patterns).map(pattern =>
37-
// globs need to be escaped on Unix
38-
platform() === 'win32' ? pattern : `'${pattern}'`,
39-
),
30+
...toArray(patterns),
4031
],
4132
ignoreExitCode: true,
4233
cwd: process.cwd(),

packages/plugin-js-packages/src/lib/runner/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
createRunnerFiles,
66
ensureDirectoryExists,
77
executeProcess,
8-
filePathToCliArg,
98
isPromiseFulfilledResult,
109
isPromiseRejectedResult,
1110
objectFromEntries,
@@ -39,7 +38,7 @@ export async function createRunnerConfig(
3938
return {
4039
command: 'node',
4140
args: [
42-
filePathToCliArg(scriptPath),
41+
scriptPath,
4342
...objectToCliArgs({ runnerConfigPath, runnerOutputPath }),
4443
],
4544
configFile: runnerConfigPath,

packages/utils/src/lib/execute-process.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
spawn,
77
} from 'node:child_process';
88
import type { Readable, Writable } from 'node:stream';
9+
import { quote } from 'shell-quote';
910
import { isVerbose } from './env.js';
1011
import { formatCommandLog } from './format-command-log.js';
1112
import { ui } from './logging.js';
@@ -157,9 +158,11 @@ export function executeProcess(cfg: ProcessConfig): Promise<ProcessResult> {
157158
);
158159
}
159160

161+
const bin = [command, quote(args ?? [])].join(' ');
162+
160163
return new Promise((resolve, reject) => {
161164
// shell:true tells Windows to use shell command for spawning a child process
162-
const spawnedProcess = spawn(command, args ?? [], {
165+
const spawnedProcess = spawn(bin, {
163166
shell: true,
164167
windowsHide: true,
165168
...options,

testing/test-nx-utils/src/lib/utils/nx.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export async function nxShowProjectJson<T extends ProjectConfiguration>(
8484
) {
8585
const { code, stderr, stdout } = await executeProcess({
8686
command: 'npx',
87-
args: ['nx', 'show', `project --json ${project}`],
87+
args: ['nx', 'show', 'project', '--json', project],
8888
cwd,
8989
});
9090

0 commit comments

Comments
 (0)