From 93676222fc041102c5580d4df80bf5256994cc28 Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Thu, 30 Apr 2026 08:38:05 -0300 Subject: [PATCH 1/2] lib: handle --permission-audit when propagating flags Signed-off-by: RafaelGSS --- lib/child_process.js | 3 +- lib/ffi.js | 6 +- lib/internal/process/permission.js | 10 +- ...ssion-audit-child-process-inherit-flags.js | 94 +++++++++++++++++++ 4 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 test/parallel/test-permission-audit-child-process-inherit-flags.js diff --git a/lib/child_process.js b/lib/child_process.js index bba860a78fe20e..824af65556e32b 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -549,7 +549,8 @@ function getPermissionModelFlagsToCopy() { function copyPermissionModelFlagsToEnv(env, key, args) { // Do not override if permission was already passed to file - if (args.includes('--permission') || (env[key] && env[key].indexOf('--permission') !== -1)) { + if (args.includes('--permission') || args.includes('--permission-audit') || + (env[key] && env[key].indexOf('--permission') !== -1)) { return; } diff --git a/lib/ffi.js b/lib/ffi.js index 98af095e0cb01c..b3a1563b520dcc 100644 --- a/lib/ffi.js +++ b/lib/ffi.js @@ -61,7 +61,11 @@ DynamicLibrary.prototype[SymbolDispose] = function() { }; function checkFFIPermission() { - if (!permission.isEnabled() || permission.has('ffi')) { + if (!permission.isEnabled()) { + return; + } + + if (permission.has('ffi') || permission.isAuditMode()) { return; } diff --git a/lib/internal/process/permission.js b/lib/internal/process/permission.js index 97ea0265fa15d9..b5da69d08c455e 100644 --- a/lib/internal/process/permission.js +++ b/lib/internal/process/permission.js @@ -11,6 +11,7 @@ const { Buffer } = require('buffer'); const { isBuffer } = Buffer; let _permission; +let _audit; let _ffi; module.exports = ObjectFreeze({ @@ -18,10 +19,17 @@ module.exports = ObjectFreeze({ isEnabled() { if (_permission === undefined) { const { getOptionValue } = require('internal/options'); - _permission = getOptionValue('--permission'); + _permission = getOptionValue('--permission') || getOptionValue('--permission-audit'); } return _permission; }, + isAuditMode() { + if (_audit === undefined) { + const { getOptionValue } = require('internal/options'); + _audit = getOptionValue('--permission-audit'); + } + return _audit; + }, has(scope, reference) { validateString(scope, 'scope'); if (reference != null) { diff --git a/test/parallel/test-permission-audit-child-process-inherit-flags.js b/test/parallel/test-permission-audit-child-process-inherit-flags.js new file mode 100644 index 00000000000000..b7bc26d1715197 --- /dev/null +++ b/test/parallel/test-permission-audit-child-process-inherit-flags.js @@ -0,0 +1,94 @@ +// Flags: --permission-audit --allow-child-process --allow-fs-read=* --allow-fs-write=* +'use strict'; + +const common = require('../common'); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} +if (process.config.variables.node_without_node_options) { + common.skip('missing NODE_OPTIONS support'); +} + +const assert = require('assert'); +const childProcess = require('child_process'); + +// Verify that the parent is running in audit mode +assert.strictEqual(typeof process.permission.has, 'function'); + +{ + assert.strictEqual(process.env.NODE_OPTIONS, undefined); +} + +// Child should inherit --permission-audit and the allow-flags via NODE_OPTIONS +{ + const { status, stdout, stderr } = childProcess.spawnSync(process.execPath, + [ + '-e', + ` + console.log(typeof process.permission); + console.log(process.permission.has("fs.write")); + console.log(process.permission.has("fs.read")); + console.log(process.permission.has("child")); + `, + ] + ); + assert.strictEqual(status, 0, `stderr: ${stderr}`); + const [permType, fsWrite, fsRead, child] = stdout.toString().split('\n'); + assert.strictEqual(permType, 'object', 'child should have process.permission defined'); + assert.strictEqual(fsWrite, 'true'); + assert.strictEqual(fsRead, 'true'); + assert.strictEqual(child, 'true'); +} + +// Child spawned with explicit --permission should use its own flags, not inherit parent's +{ + const { status, stdout, stderr } = childProcess.spawnSync( + process.execPath, + [ + '--permission', + '--allow-fs-write=*', + '-e', + ` + console.log(typeof process.permission); + console.log(process.permission.has("fs.write")); + console.log(process.permission.has("fs.read")); + console.log(process.permission.has("child")); + `, + ] + ); + assert.strictEqual(status, 0, `stderr: ${stderr}`); + const [permType, fsWrite, fsRead, child] = stdout.toString().split('\n'); + assert.strictEqual(permType, 'object'); + assert.strictEqual(fsWrite, 'true'); + assert.strictEqual(fsRead, 'false'); + assert.strictEqual(child, 'false'); +} + +// Child spawned with explicit --permission-audit should use its own flags +{ + const { status, stdout, stderr } = childProcess.spawnSync( + process.execPath, + [ + '--permission-audit', + '--allow-fs-write=*', + '-e', + ` + console.log(typeof process.permission); + console.log(process.permission.has("fs.write")); + console.log(process.permission.has("fs.read")); + `, + ] + ); + assert.strictEqual(status, 0, `stderr: ${stderr}`); + const [permType, fsWrite, fsRead] = stdout.toString().split('\n'); + assert.strictEqual(permType, 'object'); + assert.strictEqual(fsWrite, 'true'); + // fs.read was not allowed in the explicit child flags + assert.strictEqual(fsRead, 'false'); +} + +{ + assert.strictEqual(process.env.NODE_OPTIONS, undefined); +} From b1ec186c1b720bc302c3efdf4ee09ff86c9faa44 Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Thu, 30 Apr 2026 12:11:43 -0300 Subject: [PATCH 2/2] fixup! lib: handle --permission-audit when propagating flags Signed-off-by: RafaelGSS --- ...ssion-audit-child-process-inherit-flags.js | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/test/parallel/test-permission-audit-child-process-inherit-flags.js b/test/parallel/test-permission-audit-child-process-inherit-flags.js index b7bc26d1715197..ec22220c4b2660 100644 --- a/test/parallel/test-permission-audit-child-process-inherit-flags.js +++ b/test/parallel/test-permission-audit-child-process-inherit-flags.js @@ -23,20 +23,20 @@ assert.strictEqual(typeof process.permission.has, 'function'); // Child should inherit --permission-audit and the allow-flags via NODE_OPTIONS { - const { status, stdout, stderr } = childProcess.spawnSync(process.execPath, - [ - '-e', - ` + const { status, stdout } = childProcess.spawnSync(process.execPath, + [ + '-e', + ` console.log(typeof process.permission); console.log(process.permission.has("fs.write")); console.log(process.permission.has("fs.read")); console.log(process.permission.has("child")); `, - ] + ] ); - assert.strictEqual(status, 0, `stderr: ${stderr}`); + assert.strictEqual(status, 0); const [permType, fsWrite, fsRead, child] = stdout.toString().split('\n'); - assert.strictEqual(permType, 'object', 'child should have process.permission defined'); + assert.strictEqual(permType, 'object'); assert.strictEqual(fsWrite, 'true'); assert.strictEqual(fsRead, 'true'); assert.strictEqual(child, 'true'); @@ -44,7 +44,7 @@ assert.strictEqual(typeof process.permission.has, 'function'); // Child spawned with explicit --permission should use its own flags, not inherit parent's { - const { status, stdout, stderr } = childProcess.spawnSync( + const { status, stdout } = childProcess.spawnSync( process.execPath, [ '--permission', @@ -58,7 +58,7 @@ assert.strictEqual(typeof process.permission.has, 'function'); `, ] ); - assert.strictEqual(status, 0, `stderr: ${stderr}`); + assert.strictEqual(status, 0); const [permType, fsWrite, fsRead, child] = stdout.toString().split('\n'); assert.strictEqual(permType, 'object'); assert.strictEqual(fsWrite, 'true'); @@ -68,7 +68,7 @@ assert.strictEqual(typeof process.permission.has, 'function'); // Child spawned with explicit --permission-audit should use its own flags { - const { status, stdout, stderr } = childProcess.spawnSync( + const { status, stdout } = childProcess.spawnSync( process.execPath, [ '--permission-audit', @@ -81,11 +81,10 @@ assert.strictEqual(typeof process.permission.has, 'function'); `, ] ); - assert.strictEqual(status, 0, `stderr: ${stderr}`); + assert.strictEqual(status, 0); const [permType, fsWrite, fsRead] = stdout.toString().split('\n'); assert.strictEqual(permType, 'object'); assert.strictEqual(fsWrite, 'true'); - // fs.read was not allowed in the explicit child flags assert.strictEqual(fsRead, 'false'); }