mirror of
https://github.com/nodejs/node.git
synced 2025-08-18 07:08:50 +02:00
policy: disable process.binding() when enabled
process.binding() can be used to trivially bypass restrictions imposed through a policy. Since the function is deprecated already, simply replace it with a stub when a policy is being enabled. Fixes: https://hackerone.com/bugs?report_id=1946470 PR-URL: https://github.com/nodejs-private/node-private/pull/397 Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> CVE-ID: CVE-2023-32559
This commit is contained in:
parent
4fdf70f9ab
commit
4aa0eff787
6 changed files with 65 additions and 0 deletions
|
@ -2215,6 +2215,9 @@ Type: Documentation-only (supports [`--pending-deprecation`][])
|
||||||
|
|
||||||
`process.binding()` is for use by Node.js internal code only.
|
`process.binding()` is for use by Node.js internal code only.
|
||||||
|
|
||||||
|
While `process.binding()` has not reached End-of-Life status in general, it is
|
||||||
|
unavailable when [policies][] are enabled.
|
||||||
|
|
||||||
### DEP0112: `dgram` private APIs
|
### DEP0112: `dgram` private APIs
|
||||||
|
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
|
@ -3532,6 +3535,7 @@ Consider using alternatives such as the [`mock`][] helper function.
|
||||||
[from_string_encoding]: buffer.md#static-method-bufferfromstring-encoding
|
[from_string_encoding]: buffer.md#static-method-bufferfromstring-encoding
|
||||||
[legacy URL API]: url.md#legacy-url-api
|
[legacy URL API]: url.md#legacy-url-api
|
||||||
[legacy `urlObject`]: url.md#legacy-urlobject
|
[legacy `urlObject`]: url.md#legacy-urlobject
|
||||||
|
[policies]: permissions.md#policies
|
||||||
[static methods of `crypto.Certificate()`]: crypto.md#class-certificate
|
[static methods of `crypto.Certificate()`]: crypto.md#class-certificate
|
||||||
[subpath exports]: packages.md#subpath-exports
|
[subpath exports]: packages.md#subpath-exports
|
||||||
[subpath imports]: packages.md#subpath-imports
|
[subpath imports]: packages.md#subpath-imports
|
||||||
|
|
|
@ -957,6 +957,9 @@ module.exports = {
|
||||||
//
|
//
|
||||||
// Note: Node.js specific errors must begin with the prefix ERR_
|
// Note: Node.js specific errors must begin with the prefix ERR_
|
||||||
|
|
||||||
|
E('ERR_ACCESS_DENIED',
|
||||||
|
'Access to this API has been restricted. Permission: %s',
|
||||||
|
Error);
|
||||||
E('ERR_AMBIGUOUS_ARGUMENT', 'The "%s" argument is ambiguous. %s', TypeError);
|
E('ERR_AMBIGUOUS_ARGUMENT', 'The "%s" argument is ambiguous. %s', TypeError);
|
||||||
E('ERR_ARG_NOT_ITERABLE', '%s must be iterable', TypeError);
|
E('ERR_ARG_NOT_ITERABLE', '%s must be iterable', TypeError);
|
||||||
E('ERR_ASSERTION', '%s', Error);
|
E('ERR_ASSERTION', '%s', Error);
|
||||||
|
|
|
@ -7,6 +7,7 @@ const {
|
||||||
} = primordials;
|
} = primordials;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
ERR_ACCESS_DENIED,
|
||||||
ERR_MANIFEST_TDZ,
|
ERR_MANIFEST_TDZ,
|
||||||
} = require('internal/errors').codes;
|
} = require('internal/errors').codes;
|
||||||
const { Manifest } = require('internal/policy/manifest');
|
const { Manifest } = require('internal/policy/manifest');
|
||||||
|
@ -32,6 +33,15 @@ module.exports = ObjectFreeze({
|
||||||
return o;
|
return o;
|
||||||
});
|
});
|
||||||
manifest = new Manifest(json, url);
|
manifest = new Manifest(json, url);
|
||||||
|
|
||||||
|
// process.binding() is deprecated (DEP0111) and trivially allows bypassing
|
||||||
|
// policies, so if policies are enabled, make this API unavailable.
|
||||||
|
process.binding = function binding(_module) {
|
||||||
|
throw new ERR_ACCESS_DENIED('process.binding');
|
||||||
|
};
|
||||||
|
process._linkedBinding = function _linkedBinding(_module) {
|
||||||
|
throw new ERR_ACCESS_DENIED('process._linkedBinding');
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
get manifest() {
|
get manifest() {
|
||||||
|
|
10
test/fixtures/policy/process-binding/app.js
vendored
Normal file
10
test/fixtures/policy/process-binding/app.js
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
assert.throws(() => { process.binding(); }, {
|
||||||
|
code: 'ERR_ACCESS_DENIED'
|
||||||
|
});
|
||||||
|
assert.throws(() => { process._linkedBinding(); }, {
|
||||||
|
code: 'ERR_ACCESS_DENIED'
|
||||||
|
});
|
10
test/fixtures/policy/process-binding/policy.json
vendored
Normal file
10
test/fixtures/policy/process-binding/policy.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"resources": {
|
||||||
|
"./app.js": {
|
||||||
|
"integrity": true,
|
||||||
|
"dependencies": {
|
||||||
|
"assert": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
test/parallel/test-policy-process-binding.js
Normal file
28
test/parallel/test-policy-process-binding.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
common.requireNoPackageJSONAbove();
|
||||||
|
|
||||||
|
if (!common.hasCrypto)
|
||||||
|
common.skip('missing crypto');
|
||||||
|
|
||||||
|
const fixtures = require('../common/fixtures');
|
||||||
|
|
||||||
|
const assert = require('node:assert');
|
||||||
|
const { spawnSync } = require('node:child_process');
|
||||||
|
|
||||||
|
const dep = fixtures.path('policy', 'process-binding', 'app.js');
|
||||||
|
const depPolicy = fixtures.path(
|
||||||
|
'policy',
|
||||||
|
'process-binding',
|
||||||
|
'policy.json');
|
||||||
|
const { status } = spawnSync(
|
||||||
|
process.execPath,
|
||||||
|
[
|
||||||
|
'--experimental-policy', depPolicy, dep,
|
||||||
|
],
|
||||||
|
{
|
||||||
|
stdio: 'inherit'
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert.strictEqual(status, 0);
|
Loading…
Add table
Add a link
Reference in a new issue