diff --git a/doc/api/errors.md b/doc/api/errors.md
index 902f5f5c8ea93a..e166638cbf3d94 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -1432,6 +1432,13 @@ An attempt was made to load a resource, but the resource did not match the
integrity defined by the policy manifest. See the documentation for [policy]
manifests for more information.
+
+### ERR_MANIFEST_DEPENDENCY_MISSING
+
+An attempt was made to load a resource, but the resource was not listed as a
+dependency from the location that attempted to load it. See the documentation
+for [policy] manifests for more information.
+
### ERR_MANIFEST_INTEGRITY_MISMATCH
@@ -1440,6 +1447,13 @@ entries for a resource which did not match each other. Update the manifest
entries to match in order to resolve this error. See the documentation for
[policy] manifests for more information.
+
+### ERR_MANIFEST_INVALID_RESOURCE_FIELD
+
+A policy manifest resource had an invalid value for one of its fields. Update
+the manifest entry to match in order to resolve this error. See the
+documentation for [policy] manifests for more information.
+
### ERR_MANIFEST_PARSE_POLICY
diff --git a/doc/api/policy.md b/doc/api/policy.md
index a1955f2b3ee835..d4c649636e49a8 100644
--- a/doc/api/policy.md
+++ b/doc/api/policy.md
@@ -38,7 +38,7 @@ node --experimental-policy=policy.json app.js
The policy manifest will be used to enforce constraints on code loaded by
Node.js.
-In order to mitigate tampering with policy files on disk, an integrity for
+To mitigate tampering with policy files on disk, an integrity for
the policy file itself may be provided via `--policy-integrity`.
This allows running `node` and asserting the policy file contents
even if the file is changed on disk.
@@ -105,9 +105,83 @@ When loading resources the entire URL must match including search parameters
and hash fragment. `./a.js?b` will not be used when attempting to load
`./a.js` and vice versa.
-In order to generate integrity strings, a script such as
+To generate integrity strings, a script such as
`printf "sha384-$(cat checked.js | openssl dgst -sha384 -binary | base64)"`
can be used.
+Integrity can be specified as the boolean value `true` to accept any
+body for the resource which can be useful for local development. It is not
+recommended in production since it would allow unexpected alteration of
+resources to be considered valid.
+
+### Dependency Redirection
+
+An application may need to ship patched versions of modules or to prevent
+modules from allowing all modules access to all other modules. Redirection
+can be used by intercepting attempts to load the modules wishing to be
+replaced.
+
+```json
+{
+ "builtins": [],
+ "resources": {
+ "./app/checked.js": {
+ "dependencies": {
+ "fs": true,
+ "os": "./app/node_modules/alt-os"
+ }
+ }
+ }
+}
+```
+
+The dependencies are keyed by the requested string specifier and have values
+of either `true` or a string pointing to a module that will be resolved.
+
+The specifier string does not perform any searching and must match exactly
+what is provided to the `require()`. Therefore, multiple specifiers may be
+needed in the policy if `require()` uses multiple different strings to point
+to the same module (such as excluding the extension).
+
+If the value of the redirection is `true` the default searching algorithms will
+be used to find the module.
+
+If the value of the redirection is a string, it will be resolved relative to
+the manifest and then immediately be used without searching.
+
+Any specifier string that is `require()`ed and not listed in the dependencies
+will result in an error according to the policy.
+
+Redirection will not prevent access to APIs through means such as direct access
+to `require.cache` and/or through `module.constructor` which allow access to
+loading modules. Policy redirection only affect specifiers to `require()`.
+Other means such as to prevent undesired access to APIs through variables are
+necessary to lock down that path of loading modules.
+
+A boolean value of `true` for the dependencies map can be specified to allow a
+module to load any specifier without redirection. This can be useful for local
+development and may have some valid usage in production, but should be used
+only with care after auditing a module to ensure its behavior is valid.
+
+#### Example: Patched Dependency
+
+Since a dependency can be redirected, you can provide attenuated or modified
+forms of dependencies as fits your application. For example, you could log
+data about timing of function durations by wrapping the original:
+
+```js
+const original = require('fn');
+module.exports = function fn(...args) {
+ console.time();
+ try {
+ return new.target ?
+ Reflect.construct(original, args) :
+ Reflect.apply(original, this, args);
+ } finally {
+ console.timeEnd();
+ }
+};
+```
+
[relative url string]: https://url.spec.whatwg.org/#relative-url-with-fragment-string
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index 64e5a2773b9aaf..cc60bf5ab8fd17 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -1033,9 +1033,15 @@ E('ERR_MANIFEST_ASSERT_INTEGRITY',
}
return msg;
}, Error);
+E('ERR_MANIFEST_DEPENDENCY_MISSING',
+ 'Manifest resource %s does not list %s as a dependency specifier',
+ Error);
E('ERR_MANIFEST_INTEGRITY_MISMATCH',
'Manifest resource %s has multiple entries but integrity lists do not match',
SyntaxError);
+E('ERR_MANIFEST_INVALID_RESOURCE_FIELD',
+ 'Manifest resource %s has invalid property value for %s',
+ TypeError);
E('ERR_MANIFEST_TDZ', 'Manifest initialization has not yet run', Error);
E('ERR_MANIFEST_UNKNOWN_ONERROR',
'Manifest specified unknown error behavior "%s".',
diff --git a/lib/internal/modules/cjs/helpers.js b/lib/internal/modules/cjs/helpers.js
index 71abcbf880ebb1..5e0e1b06ae3a1c 100644
--- a/lib/internal/modules/cjs/helpers.js
+++ b/lib/internal/modules/cjs/helpers.js
@@ -1,19 +1,72 @@
'use strict';
const { Object } = primordials;
+const {
+ ERR_MANIFEST_DEPENDENCY_MISSING,
+ ERR_UNKNOWN_BUILTIN_MODULE
+} = require('internal/errors').codes;
+const { NativeModule } = require('internal/bootstrap/loaders');
+const { getOptionValue } = require('internal/options');
+const experimentalModules = getOptionValue('--experimental-modules');
const { validateString } = require('internal/validators');
const path = require('path');
-const { pathToFileURL } = require('internal/url');
+const { pathToFileURL, fileURLToPath } = require('internal/url');
const { URL } = require('url');
+const debug = require('internal/util/debuglog').debuglog('module');
+
+function loadNativeModule(filename, request, experimentalModules) {
+ const mod = NativeModule.map.get(filename);
+ if (mod) {
+ debug('load native module %s', request);
+ mod.compileForPublicLoader(experimentalModules);
+ return mod;
+ }
+}
+
// Invoke with makeRequireFunction(module) where |module| is the Module object
// to use as the context for the require() function.
-function makeRequireFunction(mod) {
+// Use redirects to set up a mapping from a policy and restrict dependencies
+function makeRequireFunction(mod, redirects) {
const Module = mod.constructor;
- function require(path) {
- return mod.require(path);
+ let require;
+ if (redirects) {
+ const { map, reaction } = redirects;
+ const id = mod.filename || mod.id;
+ require = function require(path) {
+ let missing = true;
+ if (map === true) {
+ missing = false;
+ } else if (map.has(path)) {
+ const redirect = map.get(path);
+ if (redirect === true) {
+ missing = false;
+ } else if (typeof redirect === 'string') {
+ const parsed = new URL(redirect);
+ if (parsed.protocol === 'node:') {
+ const specifier = parsed.pathname;
+ const mod = loadNativeModule(
+ specifier,
+ redirect,
+ experimentalModules);
+ if (mod && mod.canBeRequiredByUsers) return mod.exports;
+ throw new ERR_UNKNOWN_BUILTIN_MODULE(specifier);
+ } else if (parsed.protocol === 'file:') {
+ return mod.require(fileURLToPath(parsed));
+ }
+ }
+ }
+ if (missing) {
+ reaction(new ERR_MANIFEST_DEPENDENCY_MISSING(id, path));
+ }
+ return mod.require(path);
+ };
+ } else {
+ require = function require(path) {
+ return mod.require(path);
+ };
}
function resolve(request, options) {
@@ -114,6 +167,7 @@ function normalizeReferrerURL(referrer) {
module.exports = {
addBuiltinLibsToObject,
builtinLibs,
+ loadNativeModule,
makeRequireFunction,
normalizeReferrerURL,
stripBOM,
diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js
index c769ce535a8338..bdc012259068d6 100644
--- a/lib/internal/modules/cjs/loader.js
+++ b/lib/internal/modules/cjs/loader.js
@@ -46,6 +46,7 @@ const {
makeRequireFunction,
normalizeReferrerURL,
stripBOM,
+ loadNativeModule
} = require('internal/modules/cjs/helpers');
const { getOptionValue } = require('internal/options');
const preserveSymlinks = getOptionValue('--preserve-symlinks');
@@ -618,11 +619,8 @@ Module._load = function(request, parent, isMain) {
return cachedModule.exports;
}
- const mod = NativeModule.map.get(filename);
- if (mod && mod.canBeRequiredByUsers) {
- debug('load native module %s', request);
- return mod.compileForPublicLoader(experimentalModules);
- }
+ const mod = loadNativeModule(filename, request, experimentalModules);
+ if (mod && mod.canBeRequiredByUsers) return mod.exports;
// Don't call updateChildren(), Module constructor already does.
const module = new Module(filename, parent);
@@ -828,8 +826,11 @@ function wrapSafe(filename, content) {
// the file.
// Returns exception, if any.
Module.prototype._compile = function(content, filename) {
+ let moduleURL;
+ let redirects;
if (manifest) {
- const moduleURL = pathToFileURL(filename);
+ moduleURL = pathToFileURL(filename);
+ redirects = manifest.getRedirects(moduleURL);
manifest.assertIntegrity(moduleURL, content);
}
@@ -853,7 +854,7 @@ Module.prototype._compile = function(content, filename) {
}
}
const dirname = path.dirname(filename);
- const require = makeRequireFunction(this);
+ const require = makeRequireFunction(this, redirects);
var result;
const exports = this.exports;
const thisValue = exports;
@@ -942,7 +943,7 @@ function createRequireFromPath(filename) {
m.filename = proxyPath;
m.paths = Module._nodeModulePaths(m.path);
- return makeRequireFunction(m);
+ return makeRequireFunction(m, null);
}
Module.createRequireFromPath = deprecate(
diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js
index b1f2c9f2595fc7..584a3303002f3d 100644
--- a/lib/internal/modules/esm/translators.js
+++ b/lib/internal/modules/esm/translators.js
@@ -9,9 +9,9 @@ const {
StringPrototype
} = primordials;
-const { NativeModule } = require('internal/bootstrap/loaders');
const {
- stripBOM
+ stripBOM,
+ loadNativeModule
} = require('internal/modules/cjs/helpers');
const CJSModule = require('internal/modules/cjs/loader').Module;
const internalURLModule = require('internal/url');
@@ -93,11 +93,10 @@ translators.set('builtin', async function builtinStrategy(url) {
debug(`Translating BuiltinModule ${url}`);
// Slice 'node:' scheme
const id = url.slice(5);
- const module = NativeModule.map.get(id);
+ const module = loadNativeModule(id, url, true);
if (!module) {
throw new ERR_UNKNOWN_BUILTIN_MODULE(id);
}
- module.compileForPublicLoader(true);
return createDynamicModule(
[], [...module.exportKeys, 'default'], url, (reflect) => {
debug(`Loading BuiltinModule ${url}`);
diff --git a/lib/internal/policy/manifest.js b/lib/internal/policy/manifest.js
index 0714b2294b637f..f91eb5b0129d48 100644
--- a/lib/internal/policy/manifest.js
+++ b/lib/internal/policy/manifest.js
@@ -1,15 +1,20 @@
'use strict';
const {
+ SafeMap,
SafeWeakMap,
Object,
RegExpPrototype,
uncurryThis
} = primordials;
+const {
+ canBeRequiredByUsers
+} = require('internal/bootstrap/loaders').NativeModule;
const {
ERR_MANIFEST_ASSERT_INTEGRITY,
ERR_MANIFEST_INTEGRITY_MISMATCH,
+ ERR_MANIFEST_INVALID_RESOURCE_FIELD,
ERR_MANIFEST_UNKNOWN_ONERROR,
} = require('internal/errors').codes;
const debug = require('internal/util/debuglog').debuglog('policy');
@@ -24,6 +29,7 @@ const BufferEquals = uncurryThis(Buffer.prototype.equals);
const BufferToString = uncurryThis(Buffer.prototype.toString);
const { entries } = Object;
const kIntegrities = new SafeWeakMap();
+const kDependencies = new SafeWeakMap();
const kReactions = new SafeWeakMap();
const kRelativeURLStringPattern = /^\.{0,2}\//;
const { getOptionValue } = require('internal/options');
@@ -52,76 +58,121 @@ class Manifest {
const integrities = {
__proto__: null,
};
- const reactions = {
+ const dependencies = {
__proto__: null,
- integrity: REACTION_THROW,
};
+ let reaction = REACTION_THROW;
if (obj.onerror) {
const behavior = obj.onerror;
if (behavior === 'throw') {
} else if (behavior === 'exit') {
- reactions.integrity = REACTION_EXIT;
+ reaction = REACTION_EXIT;
} else if (behavior === 'log') {
- reactions.integrity = REACTION_LOG;
+ reaction = REACTION_LOG;
} else {
throw new ERR_MANIFEST_UNKNOWN_ONERROR(behavior);
}
}
- kReactions.set(this, Object.freeze(reactions));
+ kReactions.set(this, reaction);
const manifestEntries = entries(obj.resources);
for (var i = 0; i < manifestEntries.length; i++) {
let url = manifestEntries[i][0];
- const integrity = manifestEntries[i][1].integrity;
+ const originalURL = url;
+ if (RegExpPrototype.test(kRelativeURLStringPattern, url)) {
+ url = new URL(url, manifestURL).href;
+ }
+ let integrity = manifestEntries[i][1].integrity;
+ if (!integrity) integrity = null;
if (integrity != null) {
- debug(`Manifest contains integrity for url ${url}`);
- if (RegExpPrototype.test(kRelativeURLStringPattern, url)) {
- url = new URL(url, manifestURL).href;
- }
+ debug(`Manifest contains integrity for url ${originalURL}`);
+ if (typeof integrity === 'string') {
+ const sri = Object.freeze(SRI.parse(integrity));
+ if (url in integrities) {
+ const old = integrities[url];
+ let mismatch = false;
- const sri = Object.freeze(SRI.parse(integrity));
- if (url in integrities) {
- const old = integrities[url];
- let mismatch = false;
-
- if (old.length !== sri.length) {
- mismatch = true;
- } else {
- compare:
- for (var sriI = 0; sriI < sri.length; sriI++) {
- for (var oldI = 0; oldI < old.length; oldI++) {
- if (sri[sriI].algorithm === old[oldI].algorithm &&
- BufferEquals(sri[sriI].value, old[oldI].value) &&
- sri[sriI].options === old[oldI].options) {
- continue compare;
+ if (old.length !== sri.length) {
+ mismatch = true;
+ } else {
+ compare:
+ for (var sriI = 0; sriI < sri.length; sriI++) {
+ for (var oldI = 0; oldI < old.length; oldI++) {
+ if (sri[sriI].algorithm === old[oldI].algorithm &&
+ BufferEquals(sri[sriI].value, old[oldI].value) &&
+ sri[sriI].options === old[oldI].options) {
+ continue compare;
+ }
}
+ mismatch = true;
+ break compare;
}
- mismatch = true;
- break compare;
}
- }
- if (mismatch) {
- throw new ERR_MANIFEST_INTEGRITY_MISMATCH(url);
+ if (mismatch) {
+ throw new ERR_MANIFEST_INTEGRITY_MISMATCH(url);
+ }
}
+ integrities[url] = sri;
+ } else if (integrity === true) {
+ integrities[url] = true;
+ } else {
+ throw new ERR_MANIFEST_INVALID_RESOURCE_FIELD(url, 'integrity');
}
- integrities[url] = sri;
+ }
+
+ let dependencyMap = manifestEntries[i][1].dependencies;
+ if (dependencyMap === null || dependencyMap === undefined) {
+ dependencyMap = {};
+ }
+ if (typeof dependencyMap === 'object' && !Array.isArray(dependencyMap)) {
+ dependencies[url] = new SafeMap(Object.entries(dependencyMap).map(
+ ([ from, to ]) => {
+ if (to === true) {
+ return [from, to];
+ }
+ if (canBeRequiredByUsers(to)) {
+ return [from, `node:${to}`];
+ } else if (RegExpPrototype.test(kRelativeURLStringPattern, to)) {
+ return [from, new URL(to, manifestURL).href];
+ }
+ return [from, new URL(to).href];
+ })
+ );
+ } else if (dependencyMap === true) {
+ dependencies[url] = true;
+ } else {
+ throw new ERR_MANIFEST_INVALID_RESOURCE_FIELD(url, 'dependencies');
}
}
Object.freeze(integrities);
kIntegrities.set(this, integrities);
+ Object.freeze(dependencies);
+ kDependencies.set(this, dependencies);
Object.freeze(this);
}
+ getRedirects(requester) {
+ const dependencies = kDependencies.get(this);
+ if (dependencies && requester in dependencies) {
+ return {
+ map: dependencies[requester],
+ reaction: kReactions.get(this)
+ };
+ }
+ return null;
+ }
+
assertIntegrity(url, content) {
debug(`Checking integrity of ${url}`);
const integrities = kIntegrities.get(this);
- const realIntegrities = new Map();
+ const realIntegrities = new SafeMap();
if (integrities && url in integrities) {
const integrityEntries = integrities[url];
+ if (integrityEntries === true) return true;
// Avoid clobbered Symbol.iterator
for (var i = 0; i < integrityEntries.length; i++) {
const {
@@ -139,7 +190,7 @@ class Manifest {
}
}
const error = new ERR_MANIFEST_ASSERT_INTEGRITY(url, realIntegrities);
- kReactions.get(this).integrity(error);
+ kReactions.get(this)(error);
}
}
diff --git a/test/common/index.mjs b/test/common/index.mjs
index 47587044020fcc..f747ee327913a5 100644
--- a/test/common/index.mjs
+++ b/test/common/index.mjs
@@ -1,12 +1,7 @@
// Flags: --experimental-modules
/* eslint-disable node-core/require-common-first, node-core/required-modules */
-import { createRequireFromPath } from 'module';
-import { fileURLToPath as toPath } from 'url';
-
-function createRequire(metaUrl) {
- return createRequireFromPath(toPath(metaUrl));
-}
+import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const common = require('./index.js');
diff --git a/test/fixtures/policy/dependencies/dependencies-empty-policy.json b/test/fixtures/policy/dependencies/dependencies-empty-policy.json
new file mode 100644
index 00000000000000..9c0389cd03928f
--- /dev/null
+++ b/test/fixtures/policy/dependencies/dependencies-empty-policy.json
@@ -0,0 +1,11 @@
+{
+ "resources": {
+ "../parent.js": {
+ "integrity": true,
+ "dependencies": {}
+ },
+ "../dep.js": {
+ "integrity": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/fixtures/policy/dependencies/dependencies-missing-policy.json b/test/fixtures/policy/dependencies/dependencies-missing-policy.json
new file mode 100644
index 00000000000000..40d2866ba5e06d
--- /dev/null
+++ b/test/fixtures/policy/dependencies/dependencies-missing-policy.json
@@ -0,0 +1,10 @@
+{
+ "resources": {
+ "../parent.js": {
+ "integrity": true
+ },
+ "../dep.js": {
+ "integrity": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/fixtures/policy/dependencies/dependencies-redirect-builtin-policy.json b/test/fixtures/policy/dependencies/dependencies-redirect-builtin-policy.json
new file mode 100644
index 00000000000000..437228a2e50277
--- /dev/null
+++ b/test/fixtures/policy/dependencies/dependencies-redirect-builtin-policy.json
@@ -0,0 +1,10 @@
+{
+ "resources": {
+ "../parent.js": {
+ "integrity": true,
+ "dependencies": {
+ "./dep.js": "node:util"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/fixtures/policy/dependencies/dependencies-redirect-policy.json b/test/fixtures/policy/dependencies/dependencies-redirect-policy.json
new file mode 100644
index 00000000000000..993a683f10a38f
--- /dev/null
+++ b/test/fixtures/policy/dependencies/dependencies-redirect-policy.json
@@ -0,0 +1,13 @@
+{
+ "resources": {
+ "../parent.js": {
+ "integrity": true,
+ "dependencies": {
+ "./dep.js": "../dep.js"
+ }
+ },
+ "../dep.js": {
+ "integrity": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/fixtures/policy/dependencies/dependencies-redirect-unknown-builtin-policy.json b/test/fixtures/policy/dependencies/dependencies-redirect-unknown-builtin-policy.json
new file mode 100644
index 00000000000000..db2046c6d36f07
--- /dev/null
+++ b/test/fixtures/policy/dependencies/dependencies-redirect-unknown-builtin-policy.json
@@ -0,0 +1,10 @@
+{
+ "resources": {
+ "../parent.js": {
+ "integrity": true,
+ "dependencies": {
+ "./dep.js": "node:404"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/fixtures/policy/dependencies/dependencies-wildcard-policy.json b/test/fixtures/policy/dependencies/dependencies-wildcard-policy.json
new file mode 100644
index 00000000000000..04ae9a318f6dc0
--- /dev/null
+++ b/test/fixtures/policy/dependencies/dependencies-wildcard-policy.json
@@ -0,0 +1,11 @@
+{
+ "resources": {
+ "../parent.js": {
+ "integrity": true,
+ "dependencies": true
+ },
+ "../dep.js": {
+ "integrity": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/fixtures/policy/parent.js b/test/fixtures/policy/parent.js
new file mode 100644
index 00000000000000..b821bfee184a35
--- /dev/null
+++ b/test/fixtures/policy/parent.js
@@ -0,0 +1,3 @@
+'use strict';
+// Included in parent-policy.json
+require('./dep.js');
diff --git a/test/message/async_error_sync_esm.out b/test/message/async_error_sync_esm.out
index 544916e24866e2..f34628ef44e52a 100644
--- a/test/message/async_error_sync_esm.out
+++ b/test/message/async_error_sync_esm.out
@@ -5,4 +5,3 @@ Error: test
at async three (*fixtures*async-error.js:20:3)
at async four (*fixtures*async-error.js:24:3)
at async main (*message*async_error_sync_esm.mjs:7:5)
-(node:*) [DEP0130] DeprecationWarning: Module.createRequireFromPath() is deprecated. Use Module.createRequire() instead.
diff --git a/test/parallel/test-policy-dependencies.js b/test/parallel/test-policy-dependencies.js
new file mode 100644
index 00000000000000..e7b2289714dff4
--- /dev/null
+++ b/test/parallel/test-policy-dependencies.js
@@ -0,0 +1,90 @@
+'use strict';
+
+const common = require('../common');
+if (!common.hasCrypto)
+ common.skip('missing crypto');
+
+const fixtures = require('../common/fixtures');
+
+const assert = require('assert');
+const { spawnSync } = require('child_process');
+
+const dep = fixtures.path('policy', 'parent.js');
+{
+ const depPolicy = fixtures.path(
+ 'policy',
+ 'dependencies',
+ 'dependencies-redirect-policy.json');
+ const { status } = spawnSync(
+ process.execPath,
+ [
+ '--experimental-policy', depPolicy, dep,
+ ]
+ );
+ assert.strictEqual(status, 0);
+}
+{
+ const depPolicy = fixtures.path(
+ 'policy',
+ 'dependencies',
+ 'dependencies-redirect-builtin-policy.json');
+ const { status } = spawnSync(
+ process.execPath,
+ [
+ '--experimental-policy', depPolicy, dep,
+ ]
+ );
+ assert.strictEqual(status, 0);
+}
+{
+ const depPolicy = fixtures.path(
+ 'policy',
+ 'dependencies',
+ 'dependencies-redirect-unknown-builtin-policy.json');
+ const { status } = spawnSync(
+ process.execPath,
+ [
+ '--experimental-policy', depPolicy, dep,
+ ]
+ );
+ assert.strictEqual(status, 1);
+}
+{
+ const depPolicy = fixtures.path(
+ 'policy',
+ 'dependencies',
+ 'dependencies-wildcard-policy.json');
+ const { status } = spawnSync(
+ process.execPath,
+ [
+ '--experimental-policy', depPolicy, dep,
+ ]
+ );
+ assert.strictEqual(status, 0);
+}
+{
+ const depPolicy = fixtures.path(
+ 'policy',
+ 'dependencies',
+ 'dependencies-empty-policy.json');
+ const { status } = spawnSync(
+ process.execPath,
+ [
+ '--experimental-policy', depPolicy, dep,
+ ]
+ );
+ assert.strictEqual(status, 1);
+}
+{
+ const depPolicy = fixtures.path(
+ 'policy',
+ 'dependencies',
+ 'dependencies-missing-policy.json');
+ const { status } = spawnSync(
+ process.execPath,
+ [
+ '--experimental-policy', depPolicy, dep,
+ ]
+ );
+ assert.strictEqual(status, 1);
+}
diff --git a/test/parallel/test-policy-integrity-flag.js b/test/parallel/test-policy-integrity-flag.js
index 3b332758d18c0a..d97ef86cbe9d0f 100644
--- a/test/parallel/test-policy-integrity-flag.js
+++ b/test/parallel/test-policy-integrity-flag.js
@@ -28,10 +28,6 @@ const windowsPolicySRI = 'sha512-OeyCPRo4OZMosHyquZXDHpuU1F4KzG9UHFnn12FMaHsvqFU
/* eslint-enable max-len */
const depPolicySRI = `${nixPolicySRI} ${windowsPolicySRI}`;
-console.dir({
- depPolicySRI,
- body: JSON.stringify(fs.readFileSync(depPolicy).toString('utf8'))
-});
{
const { status, stderr } = spawnSync(
process.execPath,
diff --git a/test/parallel/test-policy-integrity.js b/test/parallel/test-policy-integrity.js
index 86d1078d9f24b3..722b45f633174d 100644
--- a/test/parallel/test-policy-integrity.js
+++ b/test/parallel/test-policy-integrity.js
@@ -71,7 +71,8 @@ function test({
};
for (const [url, { body, match }] of Object.entries(resources)) {
manifest.resources[url] = {
- integrity: `sha256-${hash('sha256', match ? body : body + '\n')}`
+ integrity: `sha256-${hash('sha256', match ? body : body + '\n')}`,
+ dependencies: true
};
fs.writeFileSync(new URL(url, tmpdirURL.href), body);
}