Skip to content

Commit

Permalink
Subresource Integrity support for ES modules, using importmaps
Browse files Browse the repository at this point in the history
SRI support for ES modules enables using them in documents that require
SRI for certain scripts for security reasons, as well as with the move
overarching require-sri-for CSP directive.

This CL implements whatwg/html#10269
based on https://github.com/guybedford/import-maps-extensions#integrity

Change-Id: Ida563334048d013ffc658f9783f9401930dd4689
Bug: 334251999
  • Loading branch information
Yoav Weiss authored and chromium-wpt-export-bot committed Apr 15, 2024
1 parent 560c8d6 commit 1ce0a3c
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 0 deletions.
90 changes: 90 additions & 0 deletions import-maps/dynamic-integrity.html
@@ -0,0 +1,90 @@
<!DOCTYPE html>
<html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
let log;
</script>
<script type="importmap" onload="t.assert_unreached('onload')" onerror="t.done()">
{
"imports": {
"./resources/log.js?pipe=sub&name=A": "./resources/log.js?pipe=sub&name=B",
"./resources/log.js?pipe=sub&name=C": "./resources/log.js?pipe=sub&name=D",
"./resources/log.js?pipe=sub&name=G": "./resources/log.js?pipe=sub&name=F",
"./resources/log.js?pipe=sub&name=X": "./resources/log.js?pipe=sub&name=X",
"bare": "./resources/log.js?pipe=sub&name=E",
"bare2": "./resources/log.js?pipe=sub&name=F"
},
"integrity": {
"./resources/log.js?pipe=sub&name=B": "sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7",
"./resources/log.js?pipe=sub&name=C": "sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7",
"./resources/log.js?pipe=sub&name=X": "sha384-mCon9M46vUfNK2Wb3yjvBmpBw/3hwB+wMYS8IzDBng+7//R5Qao35E1azo4gFVax",
"./resources/log.js?pipe=sub&name=Y": "sha384-mCon9M46vUfNK2Wb3yjvBmpBw/3hwB+wMYS8IzDBng+7//R5Qao35E1azo4gFVax",
"./resources/log.js?pipe=sub&name=E": "sha384-Li9vy3DqF8tnTXuiaAJuML3ky+tr10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7",
"bare2": "sha384-Li9vy3DqF8tnTXuiaAJuML3ky+tr10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7"
}
}
</script>
<script type="module">
promise_test(() => {
log = [];
return import("./resources/log.js?pipe=sub&name=A")
.then(() => assert_unreached())
.catch(() => assert_equals(log.length, 0))
},
'script was not loaded, as its resolved URL failed its integrity check');

promise_test(() => {
log = [];
return import("./resources/log.js?pipe=sub&name=C")
.then(() => {
assert_equals(log.length, 1);
assert_equals(log[0], "log:D");
})
.catch((e) => assert_unreached(e))
},
'script was loaded, as its resolved URL had no integrity check, despite' +
' its specifier having one');

promise_test(() => {
log = [];
return import("./resources/log.js?pipe=sub&name=X")
.then(() => {
assert_equals(log.length, 1);
assert_equals(log[0], "log:X");
})
.catch((e) => assert_unreached(e))
},
'script was loaded, as its integrity check passed');

promise_test(() => {
log = [];
return import("./resources/log.js?pipe=sub&name=Y")
.then(() => assert_unreached())
.catch(() => assert_equals(log.length, 0))
},
'Script with no import definition was not loaded, as it failed its' +
' integrity check');

promise_test(() => {
log = [];
return import("bare")
.then(() => assert_unreached())
.catch(() => assert_equals(log.length, 0))
},
'Bare specifier script was not loaded, as it failed its integrity check');

promise_test(() => {
log = [];
return import("bare2")
.then(() => {
assert_equals(log.length, 1);
assert_equals(log[0], "log:F");
})
.catch((e) => assert_unreached(e))
},
'Bare specifier used for integrity loaded, as its definition should have' +
' used the URL');

</script>

70 changes: 70 additions & 0 deletions import-maps/static-integrity.html
@@ -0,0 +1,70 @@
<!DOCTYPE html>
<html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
let log = [];
</script>
<script type="importmap">
{
"imports": {
"./resources/log.js?pipe=sub&name=A": "./resources/log.js?pipe=sub&name=B",
"./resources/log.js?pipe=sub&name=C": "./resources/log.js?pipe=sub&name=D"
},
"integrity": {
"./resources/log.js?pipe=sub&name=B": "sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7",
"./resources/log.js?pipe=sub&name=D": "sha384-rxZqznFuOnvObm6JJKVmwzBXrsRG25IepqKDFHGhtitRu9YPjxPpRPMIu2hzvtxF",
"./resources/log.js?pipe=sub&name=X": "sha384-mCon9M46vUfNK2Wb3yjvBmpBw/3hwB+wMYS8IzDBng+7//R5Qao35E1azo4gFVzx",
"./resources/log.js?pipe=sub&name=Y": "sha384-u0yaFlBF39Au++qcn+MGL/Ml7UmuVfLymNJAz6Yyi4RqyUfWelcuAzVyE8Shs9xn",
"./resources/log.js?pipe=sub&name=Z": "sha384-u0yaFlBF39Au++qcn+MGL/Ml7UmuVfLymNJAz6Yyi4RqyUfWelcuAzVyE8Shs9xn"
}
}
</script>
<script type="module">
import './resources/log.js?pipe=sub&name=A';
</script>
<script type="module">
test(t => {
assert_array_equals(log, []);
}, 'Static script did not load as it failed its integrity check');
log = [];
</script>
<script type="module">
import './resources/log.js?pipe=sub&name=C';
</script>
<script type="module">
test(t => {
assert_array_equals(log, ["log:D"]);
}, 'Static script loaded as its integrity check passed');
log = [];
</script>
<script type="module">
import './resources/log.js?pipe=sub&name=X';
</script>
<script type="module">
test(t => {
assert_array_equals(log, []);
}, 'Static script did not load as it failed its integrity check, even' +
' without an import defined');
log = [];
</script>
<script type="module">
import './resources/log.js?pipe=sub&name=Y';
</script>
<script type="module">
test(t => {
assert_array_equals(log, ["log:Y"]);
}, 'Static script loaded as its integrity check passed without an import' +
' defined');
log = [];
</script>
<script type="module" src="./resources/log.js?pipe=sub&name=Z">;
</script>
<script type="module">
test(t => {
assert_array_equals(log, ["log:Z"]);
}, 'HTML-based module script loaded despite an integrity check that was' +
' supposed to fail, because import map integrity does not apply to' +
' HTML-based modules.');
log = [];
</script>

0 comments on commit 1ce0a3c

Please sign in to comment.