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..ec22220c4b2660 --- /dev/null +++ b/test/parallel/test-permission-audit-child-process-inherit-flags.js @@ -0,0 +1,93 @@ +// 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 } = 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); + const [permType, fsWrite, fsRead, child] = stdout.toString().split('\n'); + assert.strictEqual(permType, 'object'); + 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 } = 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); + 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 } = 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); + const [permType, fsWrite, fsRead] = stdout.toString().split('\n'); + assert.strictEqual(permType, 'object'); + assert.strictEqual(fsWrite, 'true'); + assert.strictEqual(fsRead, 'false'); +} + +{ + assert.strictEqual(process.env.NODE_OPTIONS, undefined); +}