From b18d468c96b6636baab5bda6302972165b6aea94 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Tue, 23 Jun 2026 11:30:57 +0200 Subject: [PATCH 1/4] src: fix escaping of single quotes in task runner Signed-off-by: Antoine du Hamel --- src/node_task_runner.cc | 4 ++-- test/fixtures/run-script/package.json | 1 + test/fixtures/run-script/repeat-args.js | 3 +++ test/parallel/test-node-run.js | 14 ++++++++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) create mode 100755 test/fixtures/run-script/repeat-args.js diff --git a/src/node_task_runner.cc b/src/node_task_runner.cc index 3e15a70e72660c..22c02e83e12ed6 100644 --- a/src/node_task_runner.cc +++ b/src/node_task_runner.cc @@ -171,10 +171,10 @@ std::string EscapeShell(const std::string_view input) { escaped = std::regex_replace(escaped, leadingQuotePairs, ""); escaped = std::regex_replace(escaped, tripleSingleQuote, "\\\""); #else - // Replace single quotes("'") with "\\'" and wrap the result + // Replace single quotes("'") with `'"'"'` and wrap the result // in single quotes. std::string escaped = - std::regex_replace(std::string(input), std::regex("'"), "\\'"); + std::regex_replace(std::string(input), std::regex("'"), "'\"'\"'"); escaped = "'" + escaped + "'"; // Remove excessive quote pairs and handle edge cases static const std::regex tripleSingleQuote("\\\\'''"); diff --git a/test/fixtures/run-script/package.json b/test/fixtures/run-script/package.json index 138f47f2f97408..1a6b66475ca5cf 100644 --- a/test/fixtures/run-script/package.json +++ b/test/fixtures/run-script/package.json @@ -9,6 +9,7 @@ "custom-env-windows": "custom-env.bat", "path-env": "path-env", "path-env-windows": "path-env.bat", + "repeat-args": "node repeat-args.js", "special-env-variables": "special-env-variables", "special-env-variables-windows": "special-env-variables.bat", "pwd": "pwd", diff --git a/test/fixtures/run-script/repeat-args.js b/test/fixtures/run-script/repeat-args.js new file mode 100755 index 00000000000000..0a5cf7fd80a6b9 --- /dev/null +++ b/test/fixtures/run-script/repeat-args.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node + +console.log(JSON.stringify(process.argv.slice(2))); diff --git a/test/parallel/test-node-run.js b/test/parallel/test-node-run.js index 26295256849702..34597078d59e42 100644 --- a/test/parallel/test-node-run.js +++ b/test/parallel/test-node-run.js @@ -156,6 +156,20 @@ describe('node --run [command]', () => { assert.strictEqual(child.code, 0); }); + it('handles positional arguments with quotes', async () => { + const child = await common.spawnPromisified( + process.execPath, + [ '--run', 'repeat-args', '--', 'I think therefore I\'m'], + { cwd: fixtures.path('run-script') }, + ); + assert.deepStrictEqual(child, { + stdout: `["I think therefore I'm"]\n`, + stderr: '', + code: 0, + signal: null, + }); + }); + it('should set PATH environment variable with paths appended with node_modules/.bin', async () => { const child = await common.spawnPromisified( process.execPath, From 5725120c408a51595b6ab914d5a4cef3c5973a00 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Tue, 23 Jun 2026 11:45:30 +0200 Subject: [PATCH 2/4] fixup! src: fix escaping of single quotes in task runner --- test/cctest/test_node_task_runner.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cctest/test_node_task_runner.cc b/test/cctest/test_node_task_runner.cc index a2c520d2709f2e..007522ba854687 100644 --- a/test/cctest/test_node_task_runner.cc +++ b/test/cctest/test_node_task_runner.cc @@ -32,8 +32,8 @@ TEST_F(TaskRunnerTest, EscapeShell) { {"\\$1", "'\\$1'"}, {"--arg=\"$1\"", "'--arg=\"$1\"'"}, {"--arg=node exec -c \"$1\"", "'--arg=node exec -c \"$1\"'"}, - {"--arg=node exec -c '$1'", "'--arg=node exec -c \\'$1\\''"}, - {"'--arg=node exec -c \"$1\"'", "'\\'--arg=node exec -c \"$1\"\\''"} + {"--arg=node exec -c '$1'", "'--arg=node exec -c '\"'\"'$1'\"'\"''"}, + {"'--arg=node exec -c \"$1\"'", "'\\'--arg=node exec -c \"$1\"'\"'\"''"} #endif }; From 7bd8005bb549e14d36daef3b105267f030846467 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Tue, 23 Jun 2026 12:02:50 +0200 Subject: [PATCH 3/4] fixup! src: fix escaping of single quotes in task runner --- test/cctest/test_node_task_runner.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cctest/test_node_task_runner.cc b/test/cctest/test_node_task_runner.cc index 007522ba854687..a103563384de8a 100644 --- a/test/cctest/test_node_task_runner.cc +++ b/test/cctest/test_node_task_runner.cc @@ -28,12 +28,12 @@ TEST_F(TaskRunnerTest, EscapeShell) { {"test words", "'test words'"}, {"$1", "'$1'"}, {"\"$1\"", "'\"$1\"'"}, - {"'$1'", "'\\'$1\\''"}, + {"'$1'", "\"'\"'$1'\"'\""}, {"\\$1", "'\\$1'"}, {"--arg=\"$1\"", "'--arg=\"$1\"'"}, {"--arg=node exec -c \"$1\"", "'--arg=node exec -c \"$1\"'"}, {"--arg=node exec -c '$1'", "'--arg=node exec -c '\"'\"'$1'\"'\"''"}, - {"'--arg=node exec -c \"$1\"'", "'\\'--arg=node exec -c \"$1\"'\"'\"''"} + {"'--arg=node exec -c \"$1\"'", "\"'\"'--arg=node exec -c \"$1\"'\"'\""} #endif }; From 6786cf07b61bbc035985fa7dfe2f1b83a1e3849f Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Tue, 23 Jun 2026 17:08:31 +0200 Subject: [PATCH 4/4] fixup! src: fix escaping of single quotes in task runner --- test/cctest/test_node_task_runner.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cctest/test_node_task_runner.cc b/test/cctest/test_node_task_runner.cc index a103563384de8a..1c715124bd88ee 100644 --- a/test/cctest/test_node_task_runner.cc +++ b/test/cctest/test_node_task_runner.cc @@ -28,12 +28,12 @@ TEST_F(TaskRunnerTest, EscapeShell) { {"test words", "'test words'"}, {"$1", "'$1'"}, {"\"$1\"", "'\"$1\"'"}, - {"'$1'", "\"'\"'$1'\"'\""}, + {"'$1'", "\"'\"'$1'\"'\"''"}, {"\\$1", "'\\$1'"}, {"--arg=\"$1\"", "'--arg=\"$1\"'"}, {"--arg=node exec -c \"$1\"", "'--arg=node exec -c \"$1\"'"}, {"--arg=node exec -c '$1'", "'--arg=node exec -c '\"'\"'$1'\"'\"''"}, - {"'--arg=node exec -c \"$1\"'", "\"'\"'--arg=node exec -c \"$1\"'\"'\""} + {"'--arg=node exec -c \"$1\"'", "\"'\"'--arg=node exec -c \"$1\"'\"'\"''"} #endif };