Skip to content

Commit 6bacaef

Browse files
committed
child_process: use module.exports.spawn in fork and execFile
`fork()` and `execFile()` call the locally-scoped `spawn()` function directly, bypassing any wrapping applied to `child_process.spawn` via module exports. This is inconsistent with `exec()`, which correctly uses `module.exports.execFile()`. APM tools, security monitors, and testing frameworks that wrap `child_process.spawn` to intercept child process creation silently miss processes spawned through `fork()` and `execFile()`. Fix both functions to use `module.exports.spawn()`, consistent with the existing `exec()` pattern. Signed-off-by: Daniel Lando <daniel.sorridi@gmail.com>
1 parent f1ed8d6 commit 6bacaef

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

lib/child_process.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ function fork(modulePath, args = [], options) {
171171
throw new ERR_CHILD_PROCESS_IPC_REQUIRED('options.stdio');
172172
}
173173

174-
return spawn(options.execPath, args, options);
174+
return module.exports.spawn(options.execPath, args, options);
175175
}
176176

177177
function _forkChild(fd, serializationMode) {
@@ -346,7 +346,7 @@ function execFile(file, args, options, callback) {
346346

347347
options.killSignal = sanitizeKillSignal(options.killSignal);
348348

349-
const child = spawn(file, args, {
349+
const child = module.exports.spawn(file, args, {
350350
cwd: options.cwd,
351351
env: options.env,
352352
gid: options.gid,
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const cp = require('child_process');
5+
6+
// Verify that fork() and execFile() call spawn through module.exports
7+
// so that user-level wrapping of child_process.spawn works correctly.
8+
// This is consistent with exec() which already uses module.exports.execFile().
9+
10+
if (process.argv[2] === 'child') {
11+
process.exit(0);
12+
}
13+
14+
const originalSpawn = cp.spawn;
15+
16+
// Test that fork() uses module.exports.spawn.
17+
cp.spawn = common.mustCall(function(...args) {
18+
cp.spawn = originalSpawn;
19+
return originalSpawn.apply(this, args);
20+
});
21+
22+
const child = cp.fork(__filename, ['child']);
23+
child.on('exit', common.mustCall((code) => {
24+
assert.strictEqual(code, 0);
25+
26+
// Test that execFile() uses module.exports.spawn.
27+
cp.spawn = common.mustCall(function(...args) {
28+
cp.spawn = originalSpawn;
29+
return originalSpawn.apply(this, args);
30+
});
31+
32+
cp.execFile(process.execPath, ['--version'], common.mustSucceed());
33+
}));

0 commit comments

Comments
 (0)