Implemented the report-to functionality for webkit-residing csp
The reporting api can now be used to send csp reports
Did not yet implement the content csp version of this change.
spec: https://wicg.github.io/reporting/
Bug: 726634
Change-Id: Icd5cc5699d31d0300e2bcfc6f72b636e855679ea
Reviewed-on: https://chromium-review.googlesource.com/629083
Commit-Queue: Andy Paicu <andypaicu@chromium.org>
Reviewed-by: Julia Tuttle <juliatuttle@chromium.org>
Reviewed-by: Mike West <mkwst@chromium.org>
Cr-Commit-Position: refs/heads/master@{#512107}
diff --git a/content-security-policy/reporting/reporting-api-doesnt-send-reports-without-violation.https.sub.html b/content-security-policy/reporting/reporting-api-doesnt-send-reports-without-violation.https.sub.html
new file mode 100644
index 0000000..cb38428
--- /dev/null
+++ b/content-security-policy/reporting/reporting-api-doesnt-send-reports-without-violation.https.sub.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test that reports using the report-api service are not sent when there's not validation</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <script>
+ var t1 = async_test("Test that image loads");
+ window.addEventListener("securitypolicyviolation",
+ t1.unreached_func("Should not have triggered a violation event"));
+ </script>
+ <img src='/content-security-policy/support/pass.png'
+ onload='t1.done();'
+ onerror='t1.unreached_func("The image should have loaded");'>
+
+ <script async defer src='../support/checkReport.sub.js?reportExists=false'></script>
+</body>
+</html>
diff --git a/content-security-policy/reporting/reporting-api-doesnt-send-reports-without-violation.https.sub.html.sub.headers b/content-security-policy/reporting/reporting-api-doesnt-send-reports-without-violation.https.sub.html.sub.headers
new file mode 100644
index 0000000..9a02581
--- /dev/null
+++ b/content-security-policy/reporting/reporting-api-doesnt-send-reports-without-violation.https.sub.html.sub.headers
@@ -0,0 +1,7 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: reporting-api-doesnt-send-reports-without-violation={{$id:uuid()}}; Path=/content-security-policy/reporting
+Report-To: { "url": "https://{{host}}:{{ports[https][0]}}/content-security-policy/support/report.py?op=put&reportID={{$id}}", "group": "csp-group", "max-age": 10886400 }
+Content-Security-Policy: script-src 'self' 'unsafe-inline'; img-src 'self'; report-to csp-group
diff --git a/content-security-policy/reporting/reporting-api-report-only-sends-reports-on-violation.https.sub.html b/content-security-policy/reporting/reporting-api-report-only-sends-reports-on-violation.https.sub.html
new file mode 100644
index 0000000..6165886
--- /dev/null
+++ b/content-security-policy/reporting/reporting-api-report-only-sends-reports-on-violation.https.sub.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test that report-only policies still work with report-to</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <script>
+ var t1 = async_test("Test that image does not load");
+ async_test(function(t2) {
+ window.addEventListener("securitypolicyviolation", t2.step_func(function(e) {
+ assert_equals(e.blockedURI, "{{location[scheme]}}://{{location[host]}}/content-security-policy/support/fail.png");
+ assert_equals(e.violatedDirective, "img-src");
+ t2.done();
+ }));
+ }, "Event is fired");
+ </script>
+ <img src='/content-security-policy/support/fail.png'
+ onload='t1.done();'
+ onerror='t1.unreached_func("The image should have loaded");'>
+
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=img-src%20%27none%27'></script>
+</body>
+</html>
diff --git a/content-security-policy/reporting/reporting-api-report-only-sends-reports-on-violation.https.sub.html.sub.headers b/content-security-policy/reporting/reporting-api-report-only-sends-reports-on-violation.https.sub.html.sub.headers
new file mode 100644
index 0000000..990cfaf
--- /dev/null
+++ b/content-security-policy/reporting/reporting-api-report-only-sends-reports-on-violation.https.sub.html.sub.headers
@@ -0,0 +1,7 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: reporting-api-report-only-sends-reports-on-violation={{$id:uuid()}}; Path=/content-security-policy/reporting
+Report-To: { "url": "https://{{host}}:{{ports[https][0]}}/content-security-policy/support/report.py?op=put&reportID={{$id}}", "group": "csp-group", "max-age": 10886400 }
+Content-Security-Policy-Report-Only: script-src 'self' 'unsafe-inline'; img-src 'none'; report-to csp-group
diff --git a/content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-1.https.sub.html b/content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-1.https.sub.html
new file mode 100644
index 0000000..119a027
--- /dev/null
+++ b/content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-1.https.sub.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test that report-to overrides report-uri. This tests report-uri before report-to in the policy</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <script>
+ var t1 = async_test("Test that image does not load");
+ async_test(function(t2) {
+ window.addEventListener("securitypolicyviolation", t2.step_func(function(e) {
+ assert_equals(e.blockedURI, "{{location[scheme]}}://{{location[host]}}/content-security-policy/support/fail.png");
+ assert_equals(e.violatedDirective, "img-src");
+ t2.done();
+ }));
+ }, "Event is fired");
+ </script>
+ <img src='/content-security-policy/support/fail.png'
+ onload='t1.unreached_func("The image should not have loaded");'
+ onerror='t1.done();'>
+ <!-- report-to overrides the report-uri so the report goes to a different endpoint and we should not have any reports sent to this endpoint -->
+ <script async defer src='../support/checkReport.sub.js?reportExists=false></script>
+</body>
+</html>
diff --git a/content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-1.https.sub.html.sub.headers b/content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-1.https.sub.html.sub.headers
new file mode 100644
index 0000000..c696384
--- /dev/null
+++ b/content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-1.https.sub.html.sub.headers
@@ -0,0 +1,7 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: reporting-api-report-to-overrides-report-uri-1={{$id:uuid()}}; Path=/content-security-policy/reporting
+Content-Security-Policy: script-src 'self' 'unsafe-inline'; img-src 'none'; report-uri "/content-security-policy/support/report.py?op=put&reportID={{$id}}"; report-to csp-group
+Report-To: { "url": "https://{{host}}:{{ports[https][0]}}/content-security-policy/support/report.py?op=put&reportID={{$id:uuid()}}", "group": "csp-group", "max-age": 10886400 }
diff --git a/content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-2.https.sub.html b/content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-2.https.sub.html
new file mode 100644
index 0000000..3c4d244
--- /dev/null
+++ b/content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-2.https.sub.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test that report-to overrides report-uri. This tests report-uri after report-to in the policy</title> <meta name=timeout content=long>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <script>
+ var t1 = async_test("Test that image does not load");
+ async_test(function(t2) {
+ window.addEventListener("securitypolicyviolation", t2.step_func(function(e) {
+ assert_equals(e.blockedURI, "{{location[scheme]}}://{{location[host]}}/content-security-policy/support/fail.png");
+ assert_equals(e.violatedDirective, "img-src");
+ t2.done();
+ }));
+ }, "Event is fired");
+ </script>
+ <img src='/content-security-policy/support/fail.png'
+ onload='t1.unreached_func("The image should not have loaded");'
+ onerror='t1.done();'>
+ <!-- report-to overrides the report-uri so the report goes to a different endpoint and we should not have any reports sent to this endpoint -->
+ <script async defer src='../support/checkReport.sub.js?reportExists=false></script>
+</body>
+</html>
diff --git a/content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-2.https.sub.html.sub.headers b/content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-2.https.sub.html.sub.headers
new file mode 100644
index 0000000..2ac676b
--- /dev/null
+++ b/content-security-policy/reporting/reporting-api-report-to-overrides-report-uri-2.https.sub.html.sub.headers
@@ -0,0 +1,7 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: reporting-api-report-to-overrides-report-uri-2={{$id:uuid()}}; Path=/content-security-policy/reporting
+Content-Security-Policy: script-src 'self' 'unsafe-inline'; img-src 'none'; report-to csp-group; report-uri "/content-security-policy/support/report.py?op=put&reportID={{$id}}"
+Report-To: { "url": "https://{{host}}:{{ports[https][0]}}/content-security-policy/support/report.py?op=put&reportID={{$id:uuid()}}", "group": "csp-group", "max-age": 10886400 }
diff --git a/content-security-policy/reporting/reporting-api-sends-reports-on-violation.https.sub.html b/content-security-policy/reporting/reporting-api-sends-reports-on-violation.https.sub.html
new file mode 100644
index 0000000..b2c3ada
--- /dev/null
+++ b/content-security-policy/reporting/reporting-api-sends-reports-on-violation.https.sub.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test that reports using the report-api service are sent when there's a violation</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <script>
+ var t1 = async_test("Test that image does not load");
+ async_test(function(t2) {
+ window.addEventListener("securitypolicyviolation", t2.step_func(function(e) {
+ assert_equals(e.blockedURI, "{{location[scheme]}}://{{location[host]}}/content-security-policy/support/fail.png");
+ assert_equals(e.violatedDirective, "img-src");
+ t2.done();
+ }));
+ }, "Event is fired");
+ </script>
+ <img src='/content-security-policy/support/fail.png'
+ onload='t1.unreached_func("The image should not have loaded");'
+ onerror='t1.done();'>
+
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=img-src%20%27none%27'></script>
+</body>
+</html>
diff --git a/content-security-policy/reporting/reporting-api-sends-reports-on-violation.https.sub.html.sub.headers b/content-security-policy/reporting/reporting-api-sends-reports-on-violation.https.sub.html.sub.headers
new file mode 100644
index 0000000..ff4b9e6
--- /dev/null
+++ b/content-security-policy/reporting/reporting-api-sends-reports-on-violation.https.sub.html.sub.headers
@@ -0,0 +1,7 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: reporting-api-sends-reports-on-violation={{$id:uuid()}}; Path=/content-security-policy/reporting
+Report-To: { "url": "https://{{host}}:{{ports[https][0]}}/content-security-policy/support/report.py?op=put&reportID={{$id}}", "group": "csp-group", "max-age": 10886400 }
+Content-Security-Policy: script-src 'self' 'unsafe-inline'; img-src 'none'; report-to csp-group
diff --git a/content-security-policy/reporting/securitypolicyviolation-idl.html b/content-security-policy/reporting/securitypolicyviolation-idl.html
index 2259512..237807c 100644
--- a/content-security-policy/reporting/securitypolicyviolation-idl.html
+++ b/content-security-policy/reporting/securitypolicyviolation-idl.html
@@ -38,6 +38,55 @@
long lineNumber;
long columnNumber;
};
+
+[
+ Constructor(DOMString type, optional EventInit eventInitDict),
+ Exposed=(Window,Worker)
+] interface Event {
+ readonly attribute DOMString type;
+ readonly attribute EventTarget? target;
+ readonly attribute EventTarget? currentTarget;
+ [MeasureAs=EventComposedPath, CallWith=ScriptState] sequence<EventTarget> composedPath();
+
+ const unsigned short NONE = 0;
+ const unsigned short CAPTURING_PHASE = 1;
+ const unsigned short AT_TARGET = 2;
+ const unsigned short BUBBLING_PHASE = 3;
+ readonly attribute unsigned short eventPhase;
+
+ [Measure] void stopPropagation();
+ [Measure] void stopImmediatePropagation();
+
+ readonly attribute boolean bubbles;
+ readonly attribute boolean cancelable;
+ void preventDefault();
+ readonly attribute boolean defaultPrevented;
+
+ [MeasureAs=EventComposed] readonly attribute boolean composed;
+
+ [Unforgeable] readonly attribute boolean isTrusted;
+
+ [CallWith=ScriptState] readonly attribute DOMHighResTimeStamp timeStamp;
+
+ [Measure] void initEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false);
+
+ // Non-standard APIs
+ [MeasureAs=EventSrcElement] readonly attribute EventTarget srcElement;
+ [MeasureAs=EventReturnValue, CallWith=ScriptState, ImplementedAs=legacyReturnValue] attribute boolean returnValue;
+ [MeasureAs=EventCancelBubble, CallWith=ScriptState] attribute boolean cancelBubble;
+ [MeasureAs=EventPath, CallWith=ScriptState] readonly attribute EventTarget[] path;
+};
+
+[
+ CheckSecurity=Receiver,
+ Exposed=(Window,Worker),
+ ImmutablePrototype
+] interface EventTarget {
+ [Custom=(CallPrologue,CallEpilogue)] void addEventListener(DOMString type, EventListener? listener, optional (AddEventListenerOptions or boolean) options);
+ [Custom=(CallPrologue,CallEpilogue)] void removeEventListener(DOMString type, EventListener? listener, optional (EventListenerOptions or boolean) options);
+ [ImplementedAs=dispatchEventForBindings, RaisesException] boolean dispatchEvent(Event event);
+};
+
</script>
<script>
(function() {
diff --git a/content-security-policy/support/checkReport.sub.js b/content-security-policy/support/checkReport.sub.js
index 803dc06..ba179d6 100644
--- a/content-security-policy/support/checkReport.sub.js
+++ b/content-security-policy/support/checkReport.sub.js
@@ -36,6 +36,13 @@
var reportLocation = location.protocol + "//" + location.host + "/content-security-policy/support/report.py?op=take&timeout=" + timeout + "&reportID=" + reportID;
var reportTest = async_test("Violation report status OK.");
+
+ function assert_field_value(field, value, field_name) {
+ assert_true(field.indexOf(value.split(" ")[0]) != -1,
+ field_name + " value of \"" + field + "\" did not match " +
+ value.split(" ")[0] + ".");
+ }
+
reportTest.step(function () {
var report = new XMLHttpRequest();
@@ -55,9 +62,11 @@
// is reported, not the details...
if(data["csp-report"] != undefined && data["csp-report"][reportField] != undefined) {
- assert_true(data["csp-report"][reportField].indexOf(reportValue.split(" ")[0]) != -1,
- reportField + " value of \"" + data["csp-report"][reportField] + "\" did not match " +
- reportValue.split(" ")[0] + ".");
+ assert_field_value(data["csp-report"][reportField], reportValue, reportField);
+ } else if (data[0] != undefined && data[0]["report"] != undefined && data[0]["report"][reportField] != undefined) {
+ assert_field_value(data[0]["report"][reportField], reportValue, reportField);
+ } else {
+ assert_equals("", reportField, "Expected report field could not be found in report");
}
}