CSP: Do not strip non webby URL in reports.
In https://crbug.com/1264789, developers complained non HTTP/HTTPS URLs
are not included in reports.
The restriction was mostly introduced by:
https://codereview.chromium.org/2002943002 for convenience, in order to
reuse KURL::StrippedForUseAsReferrer.
The drawback is that "webpack://node_modules/sample/script4.js" is
transformed into "webpack", since its protocol is not http/https.
This patch initially wanted to remove this restrictions by rewriting our
own version of StrippedForUseAsReferrer, without the inconvenience, and
most importantly, add 14 WPT test cases.
Last minute, I wrote a specification:
https://github.com/w3c/webappsec-csp/pull/527 and decided to prefer
using an allow-list containing ['http', 'https'] instead of a
block-list. As a result, 'webpack:' URLs continue to be stripped down to
their scheme. Sorry...
Note: There are some scheme we don't want to expose, like
['chrome-extension', 'moz-extension'].
Bug: 1264789
Change-Id: Ia967c3122915a37b119321bb327e6c969d649020
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3263879
Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org>
Reviewed-by: Mike West <mkwst@chromium.org>
Cr-Commit-Position: refs/heads/main@{#944975}
diff --git a/content-security-policy/securitypolicyviolation/blockeduri-ws-wss-scheme.html b/content-security-policy/securitypolicyviolation/blockeduri-ws-wss-scheme.html
index 1dd99f7..88bf4ae 100644
--- a/content-security-policy/securitypolicyviolation/blockeduri-ws-wss-scheme.html
+++ b/content-security-policy/securitypolicyviolation/blockeduri-ws-wss-scheme.html
@@ -23,28 +23,28 @@
}, "Install <meta> CSP");
promise_test(async test => {
- const url = get_host_info().HTTP_ORIGIN.replace("http", "ws");
+ const url = get_host_info().HTTP_ORIGIN.replace("http", "ws") + "/path";
const violation = nextCSPViolation(test);
try { new WebSocket(url); } catch (e) {}
assert_equals((await violation).blockedURI, url);
}, "ws");
promise_test(async test => {
- const url = get_host_info().HTTP_ORIGIN.replace("http", "wss");
+ const url = get_host_info().HTTP_ORIGIN.replace("http", "wss") + "/path";
const violation = nextCSPViolation(test);
try { new WebSocket(url); } catch (e) {}
assert_equals((await violation).blockedURI, url);
}, "wss");
promise_test(async test => {
- const url = get_host_info().HTTP_REMOTE_ORIGIN.replace("http", "wss");
+ const url = get_host_info().HTTP_REMOTE_ORIGIN.replace("http", "wss") + "/path";
const violation = nextCSPViolation(test);
try { new WebSocket(url); } catch (e) {}
assert_equals((await violation).blockedURI, url);
}, "cross-origin");
promise_test(async test => {
- const url = get_host_info().HTTP_ORIGIN.replace("http", "wss");
+ const url = get_host_info().HTTP_ORIGIN.replace("http", "wss") + "/path";
const violation = nextCSPViolation(test);
try {new WebSocket(redirector + "?location=" + url); } catch (e) {}
assert_equals((await violation).blockedURI, url);
diff --git a/content-security-policy/securitypolicyviolation/source-file.html b/content-security-policy/securitypolicyviolation/source-file.html
new file mode 100644
index 0000000..354b8df
--- /dev/null
+++ b/content-security-policy/securitypolicyviolation/source-file.html
@@ -0,0 +1,102 @@
+<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+const policy = trustedTypes.createPolicy("sample", {createScript: x => x});
+
+// Check CSP violated by a script originating from |input| returns a CSP
+// violation whose sourceFile is |output|.
+const testSourceFile = (description, input, output) => {
+ promise_test(async test => {
+ // Listen for TrustedType violation.
+ const violation = new Promise(resolve => {
+ document.addEventListener("securitypolicyviolation", e => {
+ resolve(e);
+ }, {once: true});
+ });
+
+ // A trusted script using a customized sourceURL. The script's execution
+ // itself will trigger a TrustedType violation.
+ const trusted_script = policy.createScript(`
+ eval('');
+ //# sourceURL=${input}
+ `)
+ try {
+ eval(trusted_script);
+ assert_unreached();
+ } catch (e) {}
+
+ assert_equals((await violation).sourceFile, output);
+ }, description);
+};
+
+testSourceFile("Basic HTTPS URL",
+ "http://dummy.test/script1.js",
+ "http://dummy.test/script1.js");
+
+testSourceFile("Basic HTTP URL",
+ "https://dummy.test/script1.js",
+ "https://dummy.test/script1.js");
+
+testSourceFile("Basic WSS URL",
+ "wss://dummy.test/script1.js",
+ "wss://dummy.test/script1.js");
+
+testSourceFile("Basic WS URL",
+ "ws://dummy.test/script1.js",
+ "ws://dummy.test/script1.js");
+
+testSourceFile("Fragment",
+ "https://dummy.test/script1.js#frag",
+ "https://dummy.test/script1.js");
+
+testSourceFile("Query",
+ "https://dummy.test/script1.js?query",
+ "https://dummy.test/script1.js");
+
+testSourceFile("Port",
+ "https://dummy.test:8080/script1.js",
+ "https://dummy.test:8080/script1.js");
+
+testSourceFile("User:password",
+ "https://user:password@dummy.test/script1.js",
+ "https://dummy.test/script1.js");
+
+testSourceFile("User",
+ "https://user@dummy.test/script1.js",
+ "https://dummy.test/script1.js");
+
+testSourceFile("Invalid URL",
+ "script2.js",
+ "");
+
+testSourceFile("file:",
+ "file:///temp/script3.js",
+ "file");
+
+testSourceFile("Custom protocol",
+ "webpack://node_modules/sample/script4.js",
+ "webpack");
+
+testSourceFile("about:blank",
+ "about:blank",
+ "about");
+
+testSourceFile("about:custom",
+ "about:custom",
+ "about");
+
+testSourceFile("data:",
+ "data:text/html;charset=utf8,<html></html>",
+ "data");
+
+testSourceFile("blob:",
+ "blob:http://test.test/012345-6789-abcd-efab-0123456789",
+ "blob");
+
+testSourceFile("javascript:",
+ "javascript:void(0)",
+ "javascript");
+
+</script>