11cb0ef41Sopenharmony_ci# Permissions
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciPermissions can be used to control what system resources the
41cb0ef41Sopenharmony_ciNode.js process has access to or what actions the process can take
51cb0ef41Sopenharmony_ciwith those resources. Permissions can also control what modules can
61cb0ef41Sopenharmony_cibe accessed by other modules.
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci* [Module-based permissions](#module-based-permissions) control which files
91cb0ef41Sopenharmony_ci  or URLs are available to other modules during application execution.
101cb0ef41Sopenharmony_ci  This can be used to control what modules can be accessed by third-party
111cb0ef41Sopenharmony_ci  dependencies, for example.
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ciIf you find a potential security vulnerability, please refer to our
141cb0ef41Sopenharmony_ci[Security Policy][].
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci## Module-based permissions
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci### Policies
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci<!--introduced_in=v11.8.0-->
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci<!-- type=misc -->
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci> Stability: 1 - Experimental
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci<!-- name=policy -->
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ciNode.js contains experimental support for creating policies on loading code.
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ciPolicies are a security feature intended to allow guarantees
311cb0ef41Sopenharmony_ciabout what code Node.js is able to load. The use of policies assumes
321cb0ef41Sopenharmony_cisafe practices for the policy files such as ensuring that policy
331cb0ef41Sopenharmony_cifiles cannot be overwritten by the Node.js application by using
341cb0ef41Sopenharmony_cifile permissions.
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ciA best practice would be to ensure that the policy manifest is read-only for
371cb0ef41Sopenharmony_cithe running Node.js application and that the file cannot be changed
381cb0ef41Sopenharmony_ciby the running Node.js application in any way. A typical setup would be to
391cb0ef41Sopenharmony_cicreate the policy file as a different user id than the one running Node.js
401cb0ef41Sopenharmony_ciand granting read permissions to the user id running Node.js.
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci#### Enabling
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci<!-- type=misc -->
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ciThe `--experimental-policy` flag can be used to enable features for policies
471cb0ef41Sopenharmony_ciwhen loading modules.
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ciOnce this has been set, all modules must conform to a policy manifest file
501cb0ef41Sopenharmony_cipassed to the flag:
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci```bash
531cb0ef41Sopenharmony_cinode --experimental-policy=policy.json app.js
541cb0ef41Sopenharmony_ci```
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ciThe policy manifest will be used to enforce constraints on code loaded by
571cb0ef41Sopenharmony_ciNode.js.
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ciTo mitigate tampering with policy files on disk, an integrity for
601cb0ef41Sopenharmony_cithe policy file itself may be provided via `--policy-integrity`.
611cb0ef41Sopenharmony_ciThis allows running `node` and asserting the policy file contents
621cb0ef41Sopenharmony_cieven if the file is changed on disk.
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci```bash
651cb0ef41Sopenharmony_cinode --experimental-policy=policy.json --policy-integrity="sha384-SggXRQHwCG8g+DktYYzxkXRIkTiEYWBHqev0xnpCxYlqMBufKZHAHQM3/boDaI/0" app.js
661cb0ef41Sopenharmony_ci```
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci#### Features
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci##### Error behavior
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ciWhen a policy check fails, Node.js by default will throw an error.
731cb0ef41Sopenharmony_ciIt is possible to change the error behavior to one of a few possibilities
741cb0ef41Sopenharmony_ciby defining an "onerror" field in a policy manifest. The following values are
751cb0ef41Sopenharmony_ciavailable to change the behavior:
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci* `"exit"`: will exit the process immediately.
781cb0ef41Sopenharmony_ci  No cleanup code will be allowed to run.
791cb0ef41Sopenharmony_ci* `"log"`: will log the error at the site of the failure.
801cb0ef41Sopenharmony_ci* `"throw"`: will throw a JS error at the site of the failure. This is the
811cb0ef41Sopenharmony_ci  default.
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci```json
841cb0ef41Sopenharmony_ci{
851cb0ef41Sopenharmony_ci  "onerror": "log",
861cb0ef41Sopenharmony_ci  "resources": {
871cb0ef41Sopenharmony_ci    "./app/checked.js": {
881cb0ef41Sopenharmony_ci      "integrity": "sha384-SggXRQHwCG8g+DktYYzxkXRIkTiEYWBHqev0xnpCxYlqMBufKZHAHQM3/boDaI/0"
891cb0ef41Sopenharmony_ci    }
901cb0ef41Sopenharmony_ci  }
911cb0ef41Sopenharmony_ci}
921cb0ef41Sopenharmony_ci```
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci##### Integrity checks
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ciPolicy files must use integrity checks with Subresource Integrity strings
971cb0ef41Sopenharmony_cicompatible with the browser
981cb0ef41Sopenharmony_ci[integrity attribute](https://www.w3.org/TR/SRI/#the-integrity-attribute)
991cb0ef41Sopenharmony_ciassociated with absolute URLs.
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ciWhen using `require()` or `import` all resources involved in loading are checked
1021cb0ef41Sopenharmony_cifor integrity if a policy manifest has been specified. If a resource does not
1031cb0ef41Sopenharmony_cimatch the integrity listed in the manifest, an error will be thrown.
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ciAn example policy file that would allow loading a file `checked.js`:
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci```json
1081cb0ef41Sopenharmony_ci{
1091cb0ef41Sopenharmony_ci  "resources": {
1101cb0ef41Sopenharmony_ci    "./app/checked.js": {
1111cb0ef41Sopenharmony_ci      "integrity": "sha384-SggXRQHwCG8g+DktYYzxkXRIkTiEYWBHqev0xnpCxYlqMBufKZHAHQM3/boDaI/0"
1121cb0ef41Sopenharmony_ci    }
1131cb0ef41Sopenharmony_ci  }
1141cb0ef41Sopenharmony_ci}
1151cb0ef41Sopenharmony_ci```
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ciEach resource listed in the policy manifest can be of one the following
1181cb0ef41Sopenharmony_ciformats to determine its location:
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci1. A [relative-URL string][] to a resource from the manifest such as `./resource.js`, `../resource.js`, or `/resource.js`.
1211cb0ef41Sopenharmony_ci2. A complete URL string to a resource such as `file:///resource.js`.
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ciWhen loading resources the entire URL must match including search parameters
1241cb0ef41Sopenharmony_ciand hash fragment. `./a.js?b` will not be used when attempting to load
1251cb0ef41Sopenharmony_ci`./a.js` and vice versa.
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ciTo generate integrity strings, a script such as
1281cb0ef41Sopenharmony_ci`node -e 'process.stdout.write("sha256-");process.stdin.pipe(crypto.createHash("sha256").setEncoding("base64")).pipe(process.stdout)' < FILE`
1291cb0ef41Sopenharmony_cican be used.
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ciIntegrity can be specified as the boolean value `true` to accept any
1321cb0ef41Sopenharmony_cibody for the resource which can be useful for local development. It is not
1331cb0ef41Sopenharmony_cirecommended in production since it would allow unexpected alteration of
1341cb0ef41Sopenharmony_ciresources to be considered valid.
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci##### Dependency redirection
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ciAn application may need to ship patched versions of modules or to prevent
1391cb0ef41Sopenharmony_cimodules from allowing all modules access to all other modules. Redirection
1401cb0ef41Sopenharmony_cican be used by intercepting attempts to load the modules wishing to be
1411cb0ef41Sopenharmony_cireplaced.
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci```json
1441cb0ef41Sopenharmony_ci{
1451cb0ef41Sopenharmony_ci  "resources": {
1461cb0ef41Sopenharmony_ci    "./app/checked.js": {
1471cb0ef41Sopenharmony_ci      "dependencies": {
1481cb0ef41Sopenharmony_ci        "fs": true,
1491cb0ef41Sopenharmony_ci        "os": "./app/node_modules/alt-os",
1501cb0ef41Sopenharmony_ci        "http": { "import": true }
1511cb0ef41Sopenharmony_ci      }
1521cb0ef41Sopenharmony_ci    }
1531cb0ef41Sopenharmony_ci  }
1541cb0ef41Sopenharmony_ci}
1551cb0ef41Sopenharmony_ci```
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ciThe dependencies are keyed by the requested specifier string and have values
1581cb0ef41Sopenharmony_ciof either `true`, `null`, a string pointing to a module to be resolved,
1591cb0ef41Sopenharmony_cior a conditions object.
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ciThe specifier string does not perform any searching and must match exactly what
1621cb0ef41Sopenharmony_ciis provided to the `require()` or `import` except for a canonicalization step.
1631cb0ef41Sopenharmony_ciTherefore, multiple specifiers may be needed in the policy if it uses multiple
1641cb0ef41Sopenharmony_cidifferent strings to point to the same module (such as excluding the extension).
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ciSpecifier strings are canonicalized but not resolved prior to be used for
1671cb0ef41Sopenharmony_cimatching in order to have some compatibility with import maps, for example if a
1681cb0ef41Sopenharmony_ciresource `file:///C:/app/server.js` was given the following redirection from a
1691cb0ef41Sopenharmony_cipolicy located at `file:///C:/app/policy.json`:
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci```json
1721cb0ef41Sopenharmony_ci{
1731cb0ef41Sopenharmony_ci  "resources": {
1741cb0ef41Sopenharmony_ci    "file:///C:/app/utils.js": {
1751cb0ef41Sopenharmony_ci      "dependencies": {
1761cb0ef41Sopenharmony_ci        "./utils.js": "./utils-v2.js"
1771cb0ef41Sopenharmony_ci      }
1781cb0ef41Sopenharmony_ci    }
1791cb0ef41Sopenharmony_ci  }
1801cb0ef41Sopenharmony_ci}
1811cb0ef41Sopenharmony_ci```
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ciAny specifier used to load `file:///C:/app/utils.js` would then be intercepted
1841cb0ef41Sopenharmony_ciand redirected to `file:///C:/app/utils-v2.js` instead regardless of using an
1851cb0ef41Sopenharmony_ciabsolute or relative specifier. However, if a specifier that is not an absolute
1861cb0ef41Sopenharmony_cior relative URL string is used, it would not be intercepted. So, if an import
1871cb0ef41Sopenharmony_cisuch as `import('#utils')` was used, it would not be intercepted.
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ciIf the value of the redirection is `true`, a "dependencies" field at the top of
1901cb0ef41Sopenharmony_cithe policy file will be used. If that field at the top of the policy file is
1911cb0ef41Sopenharmony_ci`true` the default node searching algorithms are used to find the module.
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ciIf the value of the redirection is a string, it is resolved relative to
1941cb0ef41Sopenharmony_cithe manifest and then immediately used without searching.
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ciAny specifier string for which resolution is attempted and that is not listed in
1971cb0ef41Sopenharmony_cithe dependencies results in an error according to the policy.
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ciRedirection does not prevent access to APIs through means such as direct access
2001cb0ef41Sopenharmony_cito `require.cache` or through `module.constructor` which allow access to
2011cb0ef41Sopenharmony_ciloading modules. Policy redirection only affects specifiers to `require()` and
2021cb0ef41Sopenharmony_ci`import`. Other means, such as to prevent undesired access to APIs through
2031cb0ef41Sopenharmony_civariables, are necessary to lock down that path of loading modules.
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ciA boolean value of `true` for the dependencies map can be specified to allow a
2061cb0ef41Sopenharmony_cimodule to load any specifier without redirection. This can be useful for local
2071cb0ef41Sopenharmony_cidevelopment and may have some valid usage in production, but should be used
2081cb0ef41Sopenharmony_cionly with care after auditing a module to ensure its behavior is valid.
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_ciSimilar to `"exports"` in `package.json`, dependencies can also be specified to
2111cb0ef41Sopenharmony_cibe objects containing conditions which branch how dependencies are loaded. In
2121cb0ef41Sopenharmony_cithe preceding example, `"http"` is allowed when the `"import"` condition is
2131cb0ef41Sopenharmony_cipart of loading it.
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ciA value of `null` for the resolved value causes the resolution to fail. This
2161cb0ef41Sopenharmony_cican be used to ensure some kinds of dynamic access are explicitly prevented.
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ciUnknown values for the resolved module location cause failures but are
2191cb0ef41Sopenharmony_cinot guaranteed to be forward compatible.
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci##### Example: Patched dependency
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ciRedirected dependencies can provide attenuated or modified functionality as fits
2241cb0ef41Sopenharmony_cithe application. For example, log data about timing of function durations by
2251cb0ef41Sopenharmony_ciwrapping the original:
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci```js
2281cb0ef41Sopenharmony_ciconst original = require('fn');
2291cb0ef41Sopenharmony_cimodule.exports = function fn(...args) {
2301cb0ef41Sopenharmony_ci  console.time();
2311cb0ef41Sopenharmony_ci  try {
2321cb0ef41Sopenharmony_ci    return new.target ?
2331cb0ef41Sopenharmony_ci      Reflect.construct(original, args) :
2341cb0ef41Sopenharmony_ci      Reflect.apply(original, this, args);
2351cb0ef41Sopenharmony_ci  } finally {
2361cb0ef41Sopenharmony_ci    console.timeEnd();
2371cb0ef41Sopenharmony_ci  }
2381cb0ef41Sopenharmony_ci};
2391cb0ef41Sopenharmony_ci```
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci#### Scopes
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ciUse the `"scopes"` field of a manifest to set configuration for many resources
2441cb0ef41Sopenharmony_ciat once. The `"scopes"` field works by matching resources by their segments.
2451cb0ef41Sopenharmony_ciIf a scope or resource includes `"cascade": true`, unknown specifiers will
2461cb0ef41Sopenharmony_cibe searched for in their containing scope. The containing scope for cascading
2471cb0ef41Sopenharmony_ciis found by recursively reducing the resource URL by removing segments for
2481cb0ef41Sopenharmony_ci[special schemes][], keeping trailing `"/"` suffixes, and removing the query and
2491cb0ef41Sopenharmony_cihash fragment. This leads to the eventual reduction of the URL to its origin.
2501cb0ef41Sopenharmony_ciIf the URL is non-special the scope will be located by the URL's origin. If no
2511cb0ef41Sopenharmony_ciscope is found for the origin or in the case of opaque origins, a protocol
2521cb0ef41Sopenharmony_cistring can be used as a scope. If no scope is found for the URL's protocol, a
2531cb0ef41Sopenharmony_cifinal empty string `""` scope will be used.
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ciNote, `blob:` URLs adopt their origin from the path they contain, and so a scope
2561cb0ef41Sopenharmony_ciof `"blob:https://nodejs.org"` will have no effect since no URL can have an
2571cb0ef41Sopenharmony_ciorigin of `blob:https://nodejs.org`; URLs starting with
2581cb0ef41Sopenharmony_ci`blob:https://nodejs.org/` will use `https://nodejs.org` for its origin and
2591cb0ef41Sopenharmony_cithus `https:` for its protocol scope. For opaque origin `blob:` URLs they will
2601cb0ef41Sopenharmony_cihave `blob:` for their protocol scope since they do not adopt origins.
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ci##### Example
2631cb0ef41Sopenharmony_ci
2641cb0ef41Sopenharmony_ci```json
2651cb0ef41Sopenharmony_ci{
2661cb0ef41Sopenharmony_ci  "scopes": {
2671cb0ef41Sopenharmony_ci    "file:///C:/app/": {},
2681cb0ef41Sopenharmony_ci    "file:": {},
2691cb0ef41Sopenharmony_ci    "": {}
2701cb0ef41Sopenharmony_ci  }
2711cb0ef41Sopenharmony_ci}
2721cb0ef41Sopenharmony_ci```
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ciGiven a file located at `file:///C:/app/bin/main.js`, the following scopes would
2751cb0ef41Sopenharmony_cibe checked in order:
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ci1. `"file:///C:/app/bin/"`
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_ciThis determines the policy for all file based resources within
2801cb0ef41Sopenharmony_ci`"file:///C:/app/bin/"`. This is not in the `"scopes"` field of the policy and
2811cb0ef41Sopenharmony_ciwould be skipped. Adding this scope to the policy would cause it to be used
2821cb0ef41Sopenharmony_ciprior to the `"file:///C:/app/"` scope.
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_ci2. `"file:///C:/app/"`
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ciThis determines the policy for all file based resources within
2871cb0ef41Sopenharmony_ci`"file:///C:/app/"`. This is in the `"scopes"` field of the policy and it would
2881cb0ef41Sopenharmony_cidetermine the policy for the resource at `file:///C:/app/bin/main.js`. If the
2891cb0ef41Sopenharmony_ciscope has `"cascade": true`, any unsatisfied queries about the resource would
2901cb0ef41Sopenharmony_cidelegate to the next relevant scope for `file:///C:/app/bin/main.js`, `"file:"`.
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci3. `"file:///C:/"`
2931cb0ef41Sopenharmony_ci
2941cb0ef41Sopenharmony_ciThis determines the policy for all file based resources within `"file:///C:/"`.
2951cb0ef41Sopenharmony_ciThis is not in the `"scopes"` field of the policy and would be skipped. It would
2961cb0ef41Sopenharmony_cinot be used for `file:///C:/app/bin/main.js` unless `"file:///"` is set to
2971cb0ef41Sopenharmony_cicascade or is not in the `"scopes"` of the policy.
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ci4. `"file:///"`
3001cb0ef41Sopenharmony_ci
3011cb0ef41Sopenharmony_ciThis determines the policy for all file based resources on the `localhost`. This
3021cb0ef41Sopenharmony_ciis not in the `"scopes"` field of the policy and would be skipped. It would not
3031cb0ef41Sopenharmony_cibe used for `file:///C:/app/bin/main.js` unless `"file:///"` is set to cascade
3041cb0ef41Sopenharmony_cior is not in the `"scopes"` of the policy.
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_ci5. `"file:"`
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ciThis determines the policy for all file based resources. It would not be used
3091cb0ef41Sopenharmony_cifor `file:///C:/app/bin/main.js` unless `"file:///"` is set to cascade or is not
3101cb0ef41Sopenharmony_ciin the `"scopes"` of the policy.
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_ci6. `""`
3131cb0ef41Sopenharmony_ci
3141cb0ef41Sopenharmony_ciThis determines the policy for all resources. It would not be used for
3151cb0ef41Sopenharmony_ci`file:///C:/app/bin/main.js` unless `"file:"` is set to cascade.
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci##### Integrity using scopes
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_ciSetting an integrity to `true` on a scope will set the integrity for any
3201cb0ef41Sopenharmony_ciresource not found in the manifest to `true`.
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_ciSetting an integrity to `null` on a scope will set the integrity for any
3231cb0ef41Sopenharmony_ciresource not found in the manifest to fail matching.
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ciNot including an integrity is the same as setting the integrity to `null`.
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_ci`"cascade"` for integrity checks will be ignored if `"integrity"` is explicitly
3281cb0ef41Sopenharmony_ciset.
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ciThe following example allows loading any file:
3311cb0ef41Sopenharmony_ci
3321cb0ef41Sopenharmony_ci```json
3331cb0ef41Sopenharmony_ci{
3341cb0ef41Sopenharmony_ci  "scopes": {
3351cb0ef41Sopenharmony_ci    "file:": {
3361cb0ef41Sopenharmony_ci      "integrity": true
3371cb0ef41Sopenharmony_ci    }
3381cb0ef41Sopenharmony_ci  }
3391cb0ef41Sopenharmony_ci}
3401cb0ef41Sopenharmony_ci```
3411cb0ef41Sopenharmony_ci
3421cb0ef41Sopenharmony_ci##### Dependency redirection using scopes
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_ciThe following example, would allow access to `fs` for all resources within
3451cb0ef41Sopenharmony_ci`./app/`:
3461cb0ef41Sopenharmony_ci
3471cb0ef41Sopenharmony_ci```json
3481cb0ef41Sopenharmony_ci{
3491cb0ef41Sopenharmony_ci  "resources": {
3501cb0ef41Sopenharmony_ci    "./app/checked.js": {
3511cb0ef41Sopenharmony_ci      "cascade": true,
3521cb0ef41Sopenharmony_ci      "integrity": true
3531cb0ef41Sopenharmony_ci    }
3541cb0ef41Sopenharmony_ci  },
3551cb0ef41Sopenharmony_ci  "scopes": {
3561cb0ef41Sopenharmony_ci    "./app/": {
3571cb0ef41Sopenharmony_ci      "dependencies": {
3581cb0ef41Sopenharmony_ci        "fs": true
3591cb0ef41Sopenharmony_ci      }
3601cb0ef41Sopenharmony_ci    }
3611cb0ef41Sopenharmony_ci  }
3621cb0ef41Sopenharmony_ci}
3631cb0ef41Sopenharmony_ci```
3641cb0ef41Sopenharmony_ci
3651cb0ef41Sopenharmony_ciThe following example, would allow access to `fs` for all `data:` resources:
3661cb0ef41Sopenharmony_ci
3671cb0ef41Sopenharmony_ci```json
3681cb0ef41Sopenharmony_ci{
3691cb0ef41Sopenharmony_ci  "resources": {
3701cb0ef41Sopenharmony_ci    "data:text/javascript,import('node:fs');": {
3711cb0ef41Sopenharmony_ci      "cascade": true,
3721cb0ef41Sopenharmony_ci      "integrity": true
3731cb0ef41Sopenharmony_ci    }
3741cb0ef41Sopenharmony_ci  },
3751cb0ef41Sopenharmony_ci  "scopes": {
3761cb0ef41Sopenharmony_ci    "data:": {
3771cb0ef41Sopenharmony_ci      "dependencies": {
3781cb0ef41Sopenharmony_ci        "fs": true
3791cb0ef41Sopenharmony_ci      }
3801cb0ef41Sopenharmony_ci    }
3811cb0ef41Sopenharmony_ci  }
3821cb0ef41Sopenharmony_ci}
3831cb0ef41Sopenharmony_ci```
3841cb0ef41Sopenharmony_ci
3851cb0ef41Sopenharmony_ci##### Example: import maps emulation
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ciGiven an import map:
3881cb0ef41Sopenharmony_ci
3891cb0ef41Sopenharmony_ci```json
3901cb0ef41Sopenharmony_ci{
3911cb0ef41Sopenharmony_ci  "imports": {
3921cb0ef41Sopenharmony_ci    "react": "./app/node_modules/react/index.js"
3931cb0ef41Sopenharmony_ci  },
3941cb0ef41Sopenharmony_ci  "scopes": {
3951cb0ef41Sopenharmony_ci    "./ssr/": {
3961cb0ef41Sopenharmony_ci      "react": "./app/node_modules/server-side-react/index.js"
3971cb0ef41Sopenharmony_ci    }
3981cb0ef41Sopenharmony_ci  }
3991cb0ef41Sopenharmony_ci}
4001cb0ef41Sopenharmony_ci```
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci```json
4031cb0ef41Sopenharmony_ci{
4041cb0ef41Sopenharmony_ci  "dependencies": true,
4051cb0ef41Sopenharmony_ci  "scopes": {
4061cb0ef41Sopenharmony_ci    "": {
4071cb0ef41Sopenharmony_ci      "cascade": true,
4081cb0ef41Sopenharmony_ci      "dependencies": {
4091cb0ef41Sopenharmony_ci        "react": "./app/node_modules/react/index.js"
4101cb0ef41Sopenharmony_ci      }
4111cb0ef41Sopenharmony_ci    },
4121cb0ef41Sopenharmony_ci    "./ssr/": {
4131cb0ef41Sopenharmony_ci      "cascade": true,
4141cb0ef41Sopenharmony_ci      "dependencies": {
4151cb0ef41Sopenharmony_ci        "react": "./app/node_modules/server-side-react/index.js"
4161cb0ef41Sopenharmony_ci      }
4171cb0ef41Sopenharmony_ci    }
4181cb0ef41Sopenharmony_ci  }
4191cb0ef41Sopenharmony_ci}
4201cb0ef41Sopenharmony_ci```
4211cb0ef41Sopenharmony_ci
4221cb0ef41Sopenharmony_ci[Import maps][] assume you can get any resource by default. This means
4231cb0ef41Sopenharmony_ci`"dependencies"` at the top level of the policy should be set to `true`.
4241cb0ef41Sopenharmony_ciPolicies require this to be opt-in since it enables all resources of the
4251cb0ef41Sopenharmony_ciapplication cross linkage which doesn't make sense for many scenarios. They also
4261cb0ef41Sopenharmony_ciassume any given scope has access to any scope above its allowed dependencies;
4271cb0ef41Sopenharmony_ciall scopes emulating import maps must set `"cascade": true`.
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ciImport maps only have a single top level scope for their "imports". So for
4301cb0ef41Sopenharmony_ciemulating `"imports"` use the `""` scope. For emulating `"scopes"` use the
4311cb0ef41Sopenharmony_ci`"scopes"` in a similar manner to how `"scopes"` works in import maps.
4321cb0ef41Sopenharmony_ci
4331cb0ef41Sopenharmony_ciCaveats: Policies do not use string matching for various finding of scope. They
4341cb0ef41Sopenharmony_cido URL traversals. This means things like `blob:` and `data:` URLs might not be
4351cb0ef41Sopenharmony_cientirely interoperable between the two systems. For example import maps can
4361cb0ef41Sopenharmony_cipartially match a `data:` or `blob:` URL by partitioning the URL on a `/`
4371cb0ef41Sopenharmony_cicharacter, policies intentionally cannot. For `blob:` URLs import map scopes do
4381cb0ef41Sopenharmony_cinot adopt the origin of the `blob:` URL.
4391cb0ef41Sopenharmony_ci
4401cb0ef41Sopenharmony_ciAdditionally, import maps only work on `import` so it may be desirable to add a
4411cb0ef41Sopenharmony_ci`"import"` condition to all dependency mappings.
4421cb0ef41Sopenharmony_ci
4431cb0ef41Sopenharmony_ci[Security Policy]: https://github.com/nodejs/node/blob/main/SECURITY.md
4441cb0ef41Sopenharmony_ci[import maps]: https://url.spec.whatwg.org/#relative-url-with-fragment-string
4451cb0ef41Sopenharmony_ci[relative-url string]: https://url.spec.whatwg.org/#relative-url-with-fragment-string
4461cb0ef41Sopenharmony_ci[special schemes]: https://url.spec.whatwg.org/#special-scheme
447