@@ -57,7 +57,7 @@ by defining an "onerror" field in a policy manifest. The following values are
5757available to change the behavior:
5858
5959* ` "exit" ` : will exit the process immediately.
60- No cleanup code will be allowed to run.
60+ No cleanup code will be allowed to run.
6161* ` "log" ` : will log the error at the site of the failure.
6262* ` "throw" ` : will throw a JS error at the site of the failure. This is the
6363 default.
@@ -80,9 +80,9 @@ compatible with the browser
8080[ integrity attribute] ( https://www.w3.org/TR/SRI/#the-integrity-attribute )
8181associated with absolute URLs.
8282
83- When using ` require() ` all resources involved in loading are checked for
84- integrity if a policy manifest has been specified. If a resource does not match
85- the integrity listed in the manifest, an error will be thrown.
83+ When using ` require() ` or ` import ` all resources involved in loading are checked
84+ for integrity if a policy manifest has been specified. If a resource does not
85+ match the integrity listed in the manifest, an error will be thrown.
8686
8787An example policy file that would allow loading a file ` checked.js ` :
8888
@@ -107,7 +107,7 @@ and hash fragment. `./a.js?b` will not be used when attempting to load
107107` ./a.js ` and vice versa.
108108
109109To generate integrity strings, a script such as
110- ` printf "sha384-$(cat checked.js | openssl dgst -sha384 -binary | base64)" `
110+ ` node -e 'process.stdout.write("sha256-");process.stdin.pipe(crypto.createHash("sha256").setEncoding("base64")).pipe(process.stdout)' < FILE `
111111can be used.
112112
113113Integrity can be specified as the boolean value ` true ` to accept any
@@ -140,13 +140,37 @@ The dependencies are keyed by the requested specifier string and have values
140140of either ` true ` , ` null ` , a string pointing to a module to be resolved,
141141or a conditions object.
142142
143- The specifier string does not perform any searching and must match exactly
144- what is provided to the ` require() ` or ` import ` . Therefore, multiple specifiers
145- may be needed in the policy if it uses multiple different strings to point
146- to the same module (such as excluding the extension).
143+ The specifier string does not perform any searching and must match exactly what
144+ is provided to the ` require() ` or ` import ` except for a canonicalization step.
145+ Therefore, multiple specifiers may be needed in the policy if it uses multiple
146+ different strings to point to the same module (such as excluding the extension).
147147
148- If the value of the redirection is ` true ` the default searching algorithms are
149- used to find the module.
148+ Specifier strings are canonicalized but not resolved prior to be used for
149+ matching in order to have some compatibility with import maps, for example if a
150+ resource ` file:///C:/app/server.js ` was given the following redirection from a
151+ policy located at ` file:///C:/app/policy.json ` :
152+
153+ ``` json
154+ {
155+ "resources" : {
156+ "file:///C:/app/utils.js" : {
157+ "dependencies" : {
158+ "./utils.js" : " ./utils-v2.js"
159+ }
160+ }
161+ }
162+ }
163+ ```
164+
165+ Any specifier used to load ` file:///C:/app/utils.js ` would then be intercepted
166+ and redirected to ` file:///C:/app/utils-v2.js ` instead regardless of using an
167+ absolute or relative specifier. However, if a specifier that is not an absolute
168+ or relative URL string is used, it would not be intercepted. So, if an import
169+ such as ` import('#utils') ` was used, it would not be intercepted.
170+
171+ If the value of the redirection is ` true ` , a "dependencies" field at the top of
172+ the policy file will be used. If that field at the top of the policy file is
173+ ` true ` the default node searching algorithms are used to find the module.
150174
151175If the value of the redirection is a string, it is resolved relative to
152176the manifest and then immediately used without searching.
@@ -207,7 +231,8 @@ is found by recursively reducing the resource URL by removing segments for
207231hash fragment. This leads to the eventual reduction of the URL to its origin.
208232If the URL is non-special the scope will be located by the URL's origin. If no
209233scope is found for the origin or in the case of opaque origins, a protocol
210- string can be used as a scope.
234+ string can be used as a scope. If no scope is found for the URL's protocol, a
235+ final empty string ` "" ` scope will be used.
211236
212237Note, ` blob: ` URLs adopt their origin from the path they contain, and so a scope
213238of ` "blob:https://nodejs.org" ` will have no effect since no URL can have an
@@ -216,6 +241,61 @@ origin of `blob:https://nodejs.org`; URLs starting with
216241thus ` https: ` for its protocol scope. For opaque origin ` blob: ` URLs they will
217242have ` blob: ` for their protocol scope since they do not adopt origins.
218243
244+ #### Example
245+
246+ ``` json
247+ {
248+ "scopes" : {
249+ "file:///C:/app/" : {},
250+ "file:" : {},
251+ "" : {}
252+ }
253+ }
254+ ```
255+
256+ Given a file located at ` file:///C:/app/bin/main.js ` , the following scopes would
257+ be checked in order:
258+
259+ 1 . ` "file:///C:/app/bin/" `
260+
261+ This determines the policy for all file based resources within
262+ ` "file:///C:/app/bin/" ` . This is not in the ` "scopes" ` field of the policy and
263+ would be skipped. Adding this scope to the policy would cause it to be used
264+ prior to the ` "file:///C:/app/" ` scope.
265+
266+ 2 . ` "file:///C:/app/" `
267+
268+ This determines the policy for all file based resources within
269+ ` "file:///C:/app/" ` . This is in the ` "scopes" ` field of the policy and it would
270+ determine the policy for the resource at ` file:///C:/app/bin/main.js ` . If the
271+ scope has ` "cascade": true ` , any unsatisfied queries about the resource would
272+ delegate to the next relevant scope for ` file:///C:/app/bin/main.js ` , ` "file:" ` .
273+
274+ 3 . ` "file:///C:/" `
275+
276+ This determines the policy for all file based resources within ` "file:///C:/" ` .
277+ This is not in the ` "scopes" ` field of the policy and would be skipped. It would
278+ not be used for ` file:///C:/app/bin/main.js ` unless ` "file:///" ` is set to
279+ cascade or is not in the ` "scopes" ` of the policy.
280+
281+ 4 . ` "file:///" `
282+
283+ This determines the policy for all file based resources on the ` localhost ` . This
284+ is not in the ` "scopes" ` field of the policy and would be skipped. It would not
285+ be used for ` file:///C:/app/bin/main.js ` unless ` "file:///" ` is set to cascade
286+ or is not in the ` "scopes" ` of the policy.
287+
288+ 5 . ` "file:" `
289+
290+ This determines the policy for all file based resources. It would not be used
291+ for ` file:///C:/app/bin/main.js ` unless ` "file:///" ` is set to cascade or is not
292+ in the ` "scopes" ` of the policy.
293+
294+ 6 . ` "" `
295+
296+ This determines the policy for all resources. It would not be used for
297+ ` file:///C:/app/bin/main.js ` unless ` "file:" ` is set to cascade.
298+
219299#### Integrity using scopes
220300
221301Setting an integrity to ` true ` on a scope will set the integrity for any
@@ -284,5 +364,64 @@ The following example, would allow access to `fs` for all `data:` resources:
284364}
285365```
286366
287- [ relative-URL string ] : https://url.spec.whatwg.org/#relative-url-with-fragment-string
367+ #### Example: [ import maps] [ ] emulation
368+
369+ Given an import map:
370+
371+ ``` json
372+ {
373+ "imports" : {
374+ "react" : " ./app/node_modules/react/index.js"
375+ },
376+ "scopes" : {
377+ "./ssr/" : {
378+ "react" : " ./app/node_modules/server-side-react/index.js"
379+ }
380+ }
381+ }
382+ ```
383+
384+ ``` json
385+ {
386+ "dependencies" : true ,
387+ "scopes" : {
388+ "" : {
389+ "cascade" : true ,
390+ "dependencies" : {
391+ "react" : " ./app/node_modules/react/index.js"
392+ }
393+ },
394+ "./ssr/" : {
395+ "cascade" : true ,
396+ "dependencies" : {
397+ "react" : " ./app/node_modules/server-side-react/index.js"
398+ }
399+ }
400+ }
401+ }
402+ ```
403+
404+ Import maps assume you can get any resource by default. This means
405+ ` "dependencies" ` at the top level of the policy should be set to ` true ` .
406+ Policies require this to be opt-in since it enables all resources of the
407+ application cross linkage which doesn't make sense for many scenarios. They also
408+ assume any given scope has access to any scope above its allowed dependencies;
409+ all scopes emulating import maps must set ` "cascade": true ` .
410+
411+ Import maps only have a single top level scope for their "imports". So for
412+ emulating ` "imports" ` use the ` "" ` scope. For emulating ` "scopes" ` use the
413+ ` "scopes" ` in a similar manner to how ` "scopes" ` works in import maps.
414+
415+ Caveats: Policies do not use string matching for various finding of scope. They
416+ do URL traversals. This means things like ` blob: ` and ` data: ` URLs might not be
417+ entirely interoperable between the two systems. For example import maps can
418+ partially match a ` data: ` or ` blob: ` URL by partitioning the URL on a ` / `
419+ character, policies intentionally cannot. For ` blob: ` URLs import map scopes do
420+ not adopt the origin of the ` blob: ` URL.
421+
422+ Additionally, import maps only work on ` import ` so it may be desirable to add a
423+ ` "import" ` condition to all dependency mappings.
424+
425+ [ import maps ] : https://url.spec.whatwg.org/#relative-url-with-fragment-string
426+ [ relative-url string ] : https://url.spec.whatwg.org/#relative-url-with-fragment-string
288427[ special schemes ] : https://url.spec.whatwg.org/#special-scheme
0 commit comments