1# Policies 2 3<!--introduced_in=v11.8.0--> 4<!-- type=misc --> 5 6> Stability: 1 - Experimental 7 8<!-- name=policy --> 9 10Node.js contains experimental support for creating policies on loading code. 11 12Policies are a security feature intended to allow guarantees 13about what code Node.js is able to load. The use of policies assumes 14safe practices for the policy files such as ensuring that policy 15files cannot be overwritten by the Node.js application by using 16file permissions. 17 18A best practice would be to ensure that the policy manifest is read only for 19the running Node.js application, and that the file cannot be changed 20by the running Node.js application in any way. A typical setup would be to 21create the policy file as a different user id than the one running Node.js 22and granting read permissions to the user id running Node.js. 23 24## Enabling 25 26<!-- type=misc --> 27 28The `--experimental-policy` flag can be used to enable features for policies 29when loading modules. 30 31Once this has been set, all modules must conform to a policy manifest file 32passed to the flag: 33 34```bash 35node --experimental-policy=policy.json app.js 36``` 37 38The policy manifest will be used to enforce constraints on code loaded by 39Node.js. 40 41To mitigate tampering with policy files on disk, an integrity for 42the policy file itself may be provided via `--policy-integrity`. 43This allows running `node` and asserting the policy file contents 44even if the file is changed on disk. 45 46```bash 47node --experimental-policy=policy.json --policy-integrity="sha384-SggXRQHwCG8g+DktYYzxkXRIkTiEYWBHqev0xnpCxYlqMBufKZHAHQM3/boDaI/0" app.js 48``` 49 50## Features 51 52### Error behavior 53 54When a policy check fails, Node.js by default will throw an error. 55It is possible to change the error behavior to one of a few possibilities 56by defining an "onerror" field in a policy manifest. The following values are 57available to change the behavior: 58 59* `"exit"`: will exit the process immediately. 60 No cleanup code will be allowed to run. 61* `"log"`: will log the error at the site of the failure. 62* `"throw"`: will throw a JS error at the site of the failure. This is the 63 default. 64 65```json 66{ 67 "onerror": "log", 68 "resources": { 69 "./app/checked.js": { 70 "integrity": "sha384-SggXRQHwCG8g+DktYYzxkXRIkTiEYWBHqev0xnpCxYlqMBufKZHAHQM3/boDaI/0" 71 } 72 } 73} 74``` 75 76### Integrity checks 77 78Policy files must use integrity checks with Subresource Integrity strings 79compatible with the browser 80[integrity attribute](https://www.w3.org/TR/SRI/#the-integrity-attribute) 81associated with absolute URLs. 82 83When using `require()` all resources involved in loading are checked for 84integrity if a policy manifest has been specified. If a resource does not match 85the integrity listed in the manifest, an error will be thrown. 86 87An example policy file that would allow loading a file `checked.js`: 88 89```json 90{ 91 "resources": { 92 "./app/checked.js": { 93 "integrity": "sha384-SggXRQHwCG8g+DktYYzxkXRIkTiEYWBHqev0xnpCxYlqMBufKZHAHQM3/boDaI/0" 94 } 95 } 96} 97``` 98 99Each resource listed in the policy manifest can be of one the following 100formats to determine its location: 101 1021. A [relative url string][] to a resource from the manifest such as `./resource.js`, `../resource.js`, or `/resource.js`. 1032. A complete url string to a resource such as `file:///resource.js`. 104 105When loading resources the entire URL must match including search parameters 106and hash fragment. `./a.js?b` will not be used when attempting to load 107`./a.js` and vice versa. 108 109To generate integrity strings, a script such as 110`printf "sha384-$(cat checked.js | openssl dgst -sha384 -binary | base64)"` 111can be used. 112 113Integrity can be specified as the boolean value `true` to accept any 114body for the resource which can be useful for local development. It is not 115recommended in production since it would allow unexpected alteration of 116resources to be considered valid. 117 118### Dependency redirection 119 120An application may need to ship patched versions of modules or to prevent 121modules from allowing all modules access to all other modules. Redirection 122can be used by intercepting attempts to load the modules wishing to be 123replaced. 124 125```json 126{ 127 "builtins": [], 128 "resources": { 129 "./app/checked.js": { 130 "dependencies": { 131 "fs": true, 132 "os": "./app/node_modules/alt-os" 133 } 134 } 135 } 136} 137``` 138 139The dependencies are keyed by the requested string specifier and have values 140of either `true` or a string pointing to a module that will be resolved. 141 142The specifier string does not perform any searching and must match exactly 143what is provided to the `require()`. Therefore, multiple specifiers may be 144needed in the policy if `require()` uses multiple different strings to point 145to the same module (such as excluding the extension). 146 147If the value of the redirection is `true` the default searching algorithms will 148be used to find the module. 149 150If the value of the redirection is a string, it will be resolved relative to 151the manifest and then immediately be used without searching. 152 153Any specifier string that is `require()`ed and not listed in the dependencies 154will result in an error according to the policy. 155 156Redirection will not prevent access to APIs through means such as direct access 157to `require.cache` and/or through `module.constructor` which allow access to 158loading modules. Policy redirection only affect specifiers to `require()`. 159Other means such as to prevent undesired access to APIs through variables are 160necessary to lock down that path of loading modules. 161 162A boolean value of `true` for the dependencies map can be specified to allow a 163module to load any specifier without redirection. This can be useful for local 164development and may have some valid usage in production, but should be used 165only with care after auditing a module to ensure its behavior is valid. 166 167#### Example: Patched dependency 168 169Redirected dependencies can provide attenuated or modified functionality as fits 170the application. For example, log data about timing of function durations by 171wrapping the original: 172 173```js 174const original = require('fn'); 175module.exports = function fn(...args) { 176 console.time(); 177 try { 178 return new.target ? 179 Reflect.construct(original, args) : 180 Reflect.apply(original, this, args); 181 } finally { 182 console.timeEnd(); 183 } 184}; 185``` 186 187[relative url string]: https://url.spec.whatwg.org/#relative-url-with-fragment-string 188