Bug 1464078 [wpt PR 11140] - Fixed CSP directive value parsing accepted character range, a=testonly
authorAndy Paicu <andypaicu@chromium.org>
Wed, 06 Jun 2018 14:58:13 +0000
changeset 478883 8a717234b858ef9d9e3b40459b26684288afa2c1
parent 478882 32596bd377c64faa9b90fbf47a40c0409de8822a
child 478884 a9e1b4d220b1d64291e35a15c50d04cc9356b60a
push id1757
push userffxbld-merge
push dateFri, 24 Aug 2018 17:02:43 +0000
treeherdermozilla-release@736023aebdb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1464078, 11140, 845961, 1071510, 561834
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1464078 [wpt PR 11140] - Fixed CSP directive value parsing accepted character range, a=testonly Automatic update from web-platform-testsFixed CSP directive value parsing accepted character range Bug: 845961 Change-Id: Ifc9609058cd7cbd268785db46534e3ed09da6ce3 Reviewed-on: https://chromium-review.googlesource.com/1071510 Commit-Queue: Andy Paicu <andypaicu@chromium.org> Reviewed-by: Mike West <mkwst@chromium.org> Cr-Commit-Position: refs/heads/master@{#561834} -- wpt-commits: 4fe61b99829d683a9cf0ad1b38f59b9931677531 wpt-pr: 11140
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/content-security-policy/embedded-enforcement/required_csp-header-crlf.html
testing/web-platform/tests/content-security-policy/embedded-enforcement/support/echo-required-csp.py
testing/web-platform/tests/content-security-policy/embedded-enforcement/support/testharness-helper.sub.js
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -311155,16 +311155,22 @@
     ]
    ],
    "content-security-policy/embedded-enforcement/required-csp-header-cascade.html": [
     [
      "/content-security-policy/embedded-enforcement/required-csp-header-cascade.html",
      {}
     ]
    ],
+   "content-security-policy/embedded-enforcement/required_csp-header-crlf.html": [
+    [
+     "/content-security-policy/embedded-enforcement/required_csp-header-crlf.html",
+     {}
+    ]
+   ],
    "content-security-policy/embedded-enforcement/required_csp-header.html": [
     [
      "/content-security-policy/embedded-enforcement/required_csp-header.html",
      {}
     ]
    ],
    "content-security-policy/embedded-enforcement/subsumption_algorithm-general.html": [
     [
@@ -427214,16 +427220,20 @@
   "content-security-policy/embedded-enforcement/iframe-csp-attribute.html": [
    "d5a253732352f46d33c1a58d1a3183a88daa3a75",
    "testharness"
   ],
   "content-security-policy/embedded-enforcement/required-csp-header-cascade.html": [
    "94bb2f69cbef65ac9c062fe38990b5dcf4a5812c",
    "testharness"
   ],
+  "content-security-policy/embedded-enforcement/required_csp-header-crlf.html": [
+   "5fb75d9366de1568e565a80f3199b0889301a5c2",
+   "testharness"
+  ],
   "content-security-policy/embedded-enforcement/required_csp-header.html": [
    "ad4636d3552abe07c662513a8b7673fa4e5f59d6",
    "testharness"
   ],
   "content-security-policy/embedded-enforcement/subsumption_algorithm-general.html": [
    "341815aa171886f3c7c34ddf5d7f0012d163c0da",
    "testharness"
   ],
@@ -427279,21 +427289,21 @@
    "269f68ae2a4cb96450fb6eceb7006452287d7970",
    "support"
   ],
   "content-security-policy/embedded-enforcement/support/echo-policy-multiple.py": [
    "363e06143474e3a3941fe4b96631146902351aff",
    "support"
   ],
   "content-security-policy/embedded-enforcement/support/echo-required-csp.py": [
-   "8d73332cdc154e05cdfa936d3f6b936b9c0ebdba",
+   "59c528ac637a5b2c3a934463c3c8080d58ed2fa9",
    "support"
   ],
   "content-security-policy/embedded-enforcement/support/testharness-helper.sub.js": [
-   "009dfb8482f20ce57121406d675fa83315cbd2d6",
+   "16c95220e0fd759535481069dff71803eea5e22e",
    "support"
   ],
   "content-security-policy/font-src/font-match-allowed.sub.html": [
    "4bc23af2a5a3280630e50cc4c35a9769e499b7a6",
    "testharness"
   ],
   "content-security-policy/font-src/font-mismatch-blocked.sub.html": [
    "274372eb59cca6e399d8c786d7a0f443c6f35254",
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/content-security-policy/embedded-enforcement/required_csp-header-crlf.html
@@ -0,0 +1,144 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Embedded Enforcement: Sec-Required-CSP header.</title>
+  <script src="/resources/testharness.js"></script>
+  <script src="/resources/testharnessreport.js"></script>
+  <script src="support/testharness-helper.sub.js"></script>
+</head>
+<body>
+  <script>
+    var tests = [
+      // CRLF characters
+      { "name": "\\r\\n character after directive name",
+        "csp": "script-src\r\n'unsafe-inline'",
+        "expected": null },
+      { "name": "\\r\\n character in directive value",
+        "csp": "script-src 'unsafe-inline'\r\n'unsafe-eval'",
+        "expected": null },
+      { "name": "\\n character after directive name",
+        "csp": "script-src\n'unsafe-inline'",
+        "expected": null },
+      { "name": "\\n character in directive value",
+        "csp": "script-src 'unsafe-inline'\n'unsafe-eval'",
+        "expected": null },
+      { "name": "\\r character after directive name",
+        "csp": "script-src\r'unsafe-inline'",
+        "expected": null },
+      { "name": "\\r character in directive value",
+        "csp": "script-src 'unsafe-inline'\r'unsafe-eval'",
+        "expected": null },
+        
+      // HTML encoded CRLF characters
+      { "name": "%0D%0A character after directive name",
+        "csp": "script-src%0D%0A'unsafe-inline'",
+        "expected": null },
+      { "name": "%0D%0A character in directive value",
+        "csp": "script-src 'unsafe-inline'%0D%0A'unsafe-eval'",
+        "expected": null },
+      { "name": "%0A character after directive name",
+        "csp": "script-src%0A'unsafe-inline'",
+        "expected": null },
+      { "name": "%0A character in directive value",
+        "csp": "script-src 'unsafe-inline'%0A'unsafe-eval'",
+        "expected": null },
+      { "name": "%0D character after directive name",
+        "csp": "script-src%0D'unsafe-inline'",
+        "expected": null },
+      { "name": "%0D character in directive value",
+        "csp": "script-src 'unsafe-inline'%0D'unsafe-eval'",
+        "expected": null },
+
+      // Attempt HTTP Header injection
+      { "name": "Attempt injecting after directive name using \\r\\n",
+        "csp": "script-src\r\nTest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after directive name using \\r",
+        "csp": "script-src\rTest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after directive name using \\n",
+        "csp": "script-src\nTest-Header-Injection: dummy",
+        "expected": null },
+
+      { "name": "Attempt injecting after directive value using \\r\\n",
+        "csp": "script-src example.com\r\nTest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after directive value using \\r",
+        "csp": "script-src example.com\rTest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after directive value using \\n",
+        "csp": "script-src example.com\nTest-Header-Injection: dummy",
+        "expected": null },
+
+      { "name": "Attempt injecting after semicolon using \\r\\n",
+        "csp": "script-src example.com;\r\nTest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after semicolon using \\r",
+        "csp": "script-src example.com;\rTest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after semicolon using \\n",
+        "csp": "script-src example.com;\nTest-Header-Injection: dummy",
+        "expected": null },
+
+      { "name": "Attempt injecting after space between name and value using \\r\\n",
+        "csp": "script-src \r\nTest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after space between name and value using \\r",
+        "csp": "script-src \rTest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after space between name and value using \\n",
+        "csp": "script-src \nTest-Header-Injection: dummy",
+        "expected": null },
+
+      // Attempt HTTP Header injection using URL encoded characters
+      { "name": "Attempt injecting after directive name using %0D%0A",
+        "csp": "script-src%0D%0ATest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after directive name using %0D",
+        "csp": "script-src%0DTest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after directive name using %0A",
+        "csp": "script-src%0ATest-Header-Injection: dummy",
+        "expected": null },
+
+      { "name": "Attempt injecting after directive value using %0D%0A",
+        "csp": "script-src example.com%0D%0ATest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after directive value using %0D",
+        "csp": "script-src example.com%0DTest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after directive value using %0A",
+        "csp": "script-src example.com%0ATest-Header-Injection: dummy",
+        "expected": null },
+
+      { "name": "Attempt injecting after semicolon using %0D%0A",
+        "csp": "script-src example.com;%0D%0ATest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after semicolon using %0D",
+        "csp": "script-src example.com;%0DTest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after semicolon using %0A",
+        "csp": "script-src example.com;%0ATest-Header-Injection: dummy",
+        "expected": null },
+
+      { "name": "Attempt injecting after space between name and value using %0D%0A",
+        "csp": "script-src %0D%0ATest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after space between name and value using %0D",
+        "csp": "script-src %0DTest-Header-Injection: dummy",
+        "expected": null },
+      { "name": "Attempt injecting after space between name and value using %0A",
+        "csp": "script-src %0ATest-Header-Injection: dummy",
+        "expected": null },
+
+    ];
+
+    tests.forEach(test => {
+      async_test(t =>  {
+        var url = generateURLString(Host.SAME_ORIGIN, PolicyHeader.REQUIRED_CSP);
+        assert_required_csp(t, url, test.csp, [test.expected]);
+      }, "Test CRLF: " + test.name);
+    });
+  </script>
+</body>
+</html>
--- a/testing/web-platform/tests/content-security-policy/embedded-enforcement/support/echo-required-csp.py
+++ b/testing/web-platform/tests/content-security-policy/embedded-enforcement/support/echo-required-csp.py
@@ -1,13 +1,18 @@
 import json
 def main(request, response):
+    message = {}
+
+    header = request.headers.get("Test-Header-Injection");
+    message['test_header_injection'] = header if header else None
+
     header = request.headers.get("Sec-Required-CSP");
-    message = {}
     message['required_csp'] = header if header else None
+
     second_level_iframe_code = ""
     if "include_second_level_iframe" in request.GET:
        if "second_level_iframe_csp" in request.GET and request.GET["second_level_iframe_csp"] <> "":
          second_level_iframe_code = '''<script>
             var i2 = document.createElement('iframe');
             i2.src = 'echo-required-csp.py';
             i2.csp = "{0}";
             document.body.appendChild(i2);
--- a/testing/web-platform/tests/content-security-policy/embedded-enforcement/support/testharness-helper.sub.js
+++ b/testing/web-platform/tests/content-security-policy/embedded-enforcement/support/testharness-helper.sub.js
@@ -86,16 +86,20 @@ function assert_required_csp(t, url, csp
   window.addEventListener('message', t.step_func(e => {
     if (e.source != i.contentWindow || !('required_csp' in e.data))
       return;
 
     if (expected.indexOf(e.data['required_csp']) == -1)
       assert_unreached('Child iframes have unexpected csp:"' + e.data['required_csp'] + '"');
 
     expected.splice(expected.indexOf(e.data['required_csp']), 1);
+
+    if (e.data['test_header_injection'] != null)
+      assert_unreached('HTTP header injection was successful');
+
     if (expected.length == 0)
       t.done();
   }));
 
   document.body.appendChild(i);
 }
 
 function assert_iframe_with_csp(t, url, csp, shouldBlock, urlId, blockedURI) {