From a628d7926e5cc6620f982675cdc5b34e2aab0634 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Fri, 31 Oct 2025 09:55:14 +0100 Subject: [PATCH 1/2] chore(e2e): pass test flags through to the test command --- dev-packages/e2e-tests/run.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dev-packages/e2e-tests/run.ts b/dev-packages/e2e-tests/run.ts index cb2685ec0489..23d0a6eb09cd 100644 --- a/dev-packages/e2e-tests/run.ts +++ b/dev-packages/e2e-tests/run.ts @@ -43,6 +43,8 @@ async function run(): Promise { // Allow to run a single app only via `yarn test:run ` const appName = process.argv[2] || ''; + // Forward any additional flags to the test command + const testFlags = process.argv.slice(3); const dsn = process.env.E2E_TEST_DSN || DEFAULT_DSN; @@ -87,7 +89,8 @@ async function run(): Promise { await asyncExec('volta run pnpm test:build', { env, cwd }); console.log(`Testing ${testAppPath}...`); - await asyncExec('volta run pnpm test:assert', { env, cwd }); + const testCommand = `volta run pnpm test:assert ${testFlags.join(' ')}`.trim(); + await asyncExec(testCommand, { env, cwd }); // clean up (although this is tmp, still nice to do) await rm(tmpDirPath, { recursive: true }); From 5b406bcd92b4d6176db789f24abeedad6aae030c Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Fri, 31 Oct 2025 10:01:58 +0100 Subject: [PATCH 2/2] fix: cmd injection issue --- dev-packages/e2e-tests/run.ts | 40 +++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/dev-packages/e2e-tests/run.ts b/dev-packages/e2e-tests/run.ts index 23d0a6eb09cd..5312dc664cee 100644 --- a/dev-packages/e2e-tests/run.ts +++ b/dev-packages/e2e-tests/run.ts @@ -12,17 +12,38 @@ const DEFAULT_DSN = 'https://username@domain/123'; const DEFAULT_SENTRY_ORG_SLUG = 'sentry-javascript-sdks'; const DEFAULT_SENTRY_PROJECT = 'sentry-javascript-e2e-tests'; -function asyncExec(command: string, options: { env: Record; cwd: string }): Promise { +function asyncExec( + command: string | string[], + options: { env: Record; cwd: string }, +): Promise { return new Promise((resolve, reject) => { - const process = spawn(command, { ...options, shell: true }); + // If command is an array, use spawn with separate command and args (safer) + // If command is a string, maintain backward compatibility with shell: true + let process: ReturnType; + if (typeof command === 'string') { + process = spawn(command, { ...options, shell: true }); + } else { + if (command.length === 0) { + return reject(new Error('Command array cannot be empty')); + } + const cmd = command[0]; + if (!cmd) { + return reject(new Error('Command array cannot be empty')); + } + process = spawn(cmd, command.slice(1), { ...options, shell: false }); + } - process.stdout.on('data', data => { - console.log(`${data}`); - }); + if (process.stdout) { + process.stdout.on('data', data => { + console.log(`${data}`); + }); + } - process.stderr.on('data', data => { - console.error(`${data}`); - }); + if (process.stderr) { + process.stderr.on('data', data => { + console.error(`${data}`); + }); + } process.on('error', error => { reject(error); @@ -89,7 +110,8 @@ async function run(): Promise { await asyncExec('volta run pnpm test:build', { env, cwd }); console.log(`Testing ${testAppPath}...`); - const testCommand = `volta run pnpm test:assert ${testFlags.join(' ')}`.trim(); + // Pass command and arguments as an array to prevent command injection + const testCommand = ['volta', 'run', 'pnpm', 'test:assert', ...testFlags]; await asyncExec(testCommand, { env, cwd }); // clean up (although this is tmp, still nice to do)