Title: [287783] trunk
Revision
287783
Author
katherine_che...@apple.com
Date
2022-01-07 14:22:38 -0800 (Fri, 07 Jan 2022)

Log Message

CSP: strict-dynamic is causing incorrect and unexpected behavior
https://bugs.webkit.org/show_bug.cgi?id=234756
<rdar://problem/87018316>

Reviewed by Brent Fulgham.

Source/WebCore:

Per the CSP spec, if strict-dynamic is included in the script-src
directive, 'self' and 'unsafe-inline' should be ignored. This fixes a
bug where they were only ignored if specified before 'strict-dynamic'.

Additionally, this reports the sourceURL as empty for inline scripts
instead of using the contextURL, which was unexpectedly allowing
inline scripts when "self" was used with "strict-dynamic".

Tests: http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-host-list.html
       http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-scheme-list.html
       http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-self.html
       http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-unsafe-inline.html

* dom/ScriptElement.cpp:
(WebCore::ScriptElement::requestClassicScript):
(WebCore::ScriptElement::executeClassicScript):
* page/csp/ContentSecurityPolicy.cpp:
(WebCore::ContentSecurityPolicy::allScriptPoliciesAllow const):
(WebCore::ContentSecurityPolicy::allowNonParserInsertedScripts const):
* page/csp/ContentSecurityPolicy.h:
* page/csp/ContentSecurityPolicySourceList.cpp:
(WebCore::ContentSecurityPolicySourceList::parseSource):

LayoutTests:

Add tests with re-arranged ordering of the source expressions.

* http/tests/security/contentSecurityPolicy/resources/simpleSourcedScript.js: Added.
* http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-host-list-expected.txt: Added.
* http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-host-list.html: Added.
* http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-scheme-list-expected.txt: Added.
* http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-scheme-list.html: Added.
* http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-self-expected.txt: Added.
* http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-self.html: Added.
* http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-unsafe-inline-expected.txt: Added.
* http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-unsafe-inline.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (287782 => 287783)


--- trunk/LayoutTests/ChangeLog	2022-01-07 22:21:03 UTC (rev 287782)
+++ trunk/LayoutTests/ChangeLog	2022-01-07 22:22:38 UTC (rev 287783)
@@ -1,3 +1,23 @@
+2022-01-07  Kate Cheney  <katherine_che...@apple.com>
+
+        CSP: strict-dynamic is causing incorrect and unexpected behavior
+        https://bugs.webkit.org/show_bug.cgi?id=234756
+        <rdar://problem/87018316>
+
+        Reviewed by Brent Fulgham.
+
+        Add tests with re-arranged ordering of the source expressions.
+
+        * http/tests/security/contentSecurityPolicy/resources/simpleSourcedScript.js: Added.
+        * http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-host-list-expected.txt: Added.
+        * http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-host-list.html: Added.
+        * http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-scheme-list-expected.txt: Added.
+        * http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-scheme-list.html: Added.
+        * http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-self-expected.txt: Added.
+        * http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-self.html: Added.
+        * http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-unsafe-inline-expected.txt: Added.
+        * http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-unsafe-inline.html: Added.
+
 2022-01-07  Chris Dumez  <cdu...@apple.com>
 
         Unreviewed, rebaseline imported/w3c/web-platform-tests/html/dom/idlharness.https.html properly on iOS platforms.

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/resources/simpleSourcedScript.js (0 => 287783)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/resources/simpleSourcedScript.js	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/resources/simpleSourcedScript.js	2022-01-07 22:22:38 UTC (rev 287783)
@@ -0,0 +1 @@
+window.postMessage(document.currentScript.id, "*");

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-host-list-expected.txt (0 => 287783)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-host-list-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-host-list-expected.txt	2022-01-07 22:22:38 UTC (rev 287783)
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: Refused to load http://127.0.0.1:8000/security/contentSecurityPolicy/resources/simpleSourcedScript.js because it does not appear in the script-src directive of the Content Security Policy.
+
+PASS All the expected CSP violation reports have been fired.
+

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-host-list.html (0 => 287783)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-host-list.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-host-list.html	2022-01-07 22:22:38 UTC (rev 287783)
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta http-equiv="Content-Security-Policy" content="script-src 'strict-dynamic' 127.0.0.1:8000 'nonce-dummy'">
+        <script src="" nonce='dummy'></script>
+        <script src="" nonce='dummy'></script>
+</head>
+<body>
+    <script nonce='dummy'>
+        async_test(function(t) {
+            window.addEventListener('securitypolicyviolation', t.step_func_done(function(e) {
+                assert_equals(e.effectiveDirective, 'script-src-elem');
+            }));
+        }, 'All the expected CSP violation reports have been fired.');
+    </script>
+    <script id='allowedScript' src=''></script>
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-scheme-list-expected.txt (0 => 287783)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-scheme-list-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-scheme-list-expected.txt	2022-01-07 22:22:38 UTC (rev 287783)
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: Refused to load http://127.0.0.1:8000/security/contentSecurityPolicy/resources/simpleSourcedScript.js because it does not appear in the script-src directive of the Content Security Policy.
+
+PASS All the expected CSP violation reports have been fired.
+

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-scheme-list.html (0 => 287783)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-scheme-list.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-scheme-list.html	2022-01-07 22:22:38 UTC (rev 287783)
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta http-equiv="Content-Security-Policy" content="script-src 'strict-dynamic' http: 'nonce-dummy'">
+        <script src="" nonce='dummy'></script>
+        <script src="" nonce='dummy'></script>
+</head>
+<body>
+    <script nonce='dummy'>
+        async_test(function(t) {
+            window.addEventListener('securitypolicyviolation', t.step_func_done(function(e) {
+                assert_equals(e.effectiveDirective, 'script-src-elem');
+            }));
+        }, 'All the expected CSP violation reports have been fired.');
+    </script>
+    <script id='allowedScript' src=''></script>
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-self-expected.txt (0 => 287783)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-self-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-self-expected.txt	2022-01-07 22:22:38 UTC (rev 287783)
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: Refused to load http://127.0.0.1:8000/security/contentSecurityPolicy/resources/simpleSourcedScript.js because it does not appear in the script-src directive of the Content Security Policy.
+
+PASS All the expected CSP violation reports have been fired.
+

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-self.html (0 => 287783)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-self.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-self.html	2022-01-07 22:22:38 UTC (rev 287783)
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta http-equiv="Content-Security-Policy" content="script-src 'strict-dynamic' 'self' 'nonce-dummy'">
+        <script src="" nonce='dummy'></script>
+        <script src="" nonce='dummy'></script>
+</head>
+<body>
+    <script nonce='dummy'>
+        async_test(function(t) {
+            window.addEventListener('securitypolicyviolation', t.step_func_done(function(e) {
+                assert_equals(e.effectiveDirective, 'script-src-elem');
+            }));
+        }, 'All the expected CSP violation reports have been fired.');
+    </script>
+    <script id='allowedScript' src=''></script>
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-unsafe-inline-expected.txt (0 => 287783)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-unsafe-inline-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-unsafe-inline-expected.txt	2022-01-07 22:22:38 UTC (rev 287783)
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: Refused to execute a script because it does not appear in the script-src directive of the Content Security Policy.
+
+PASS All the expected CSP violation reports have been fired.
+

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-unsafe-inline.html (0 => 287783)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-unsafe-inline.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-unsafe-inline.html	2022-01-07 22:22:38 UTC (rev 287783)
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta http-equiv="Content-Security-Policy" content="script-src 'strict-dynamic' 'unsafe-inline' 'nonce-dummy'">
+        <script src="" nonce='dummy'></script>
+        <script src="" nonce='dummy'></script>
+</head>
+<body>
+    <script nonce='dummy'>
+        async_test(function(t) {
+            window.addEventListener('securitypolicyviolation', t.step_func_done(function(e) {
+                assert_equals(e.effectiveDirective, 'script-src-elem');
+            }));
+        }, 'All the expected CSP violation reports have been fired.');
+    </script>
+    <script nonce='wrong'>
+        assert_unreached('Inline script with an incorrect nonce should not be executed.');
+    </script>
+</body>
+</html>

Modified: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-module-script-expected.txt (287782 => 287783)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-module-script-expected.txt	2022-01-07 22:21:03 UTC (rev 287782)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/strict-dynamic-module-script-expected.txt	2022-01-07 22:22:38 UTC (rev 287783)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: Refused to load http://127.0.0.1:8000/security/contentSecurityPolicy/strict-dynamic-module-script.html because it does not appear in the script-src directive of the Content Security Policy.
+CONSOLE MESSAGE: Refused to execute a script because it does not appear in the script-src directive of the Content Security Policy.
 
 PASS All the expected CSP violation reports have been fired.
 

Modified: trunk/Source/WebCore/ChangeLog (287782 => 287783)


--- trunk/Source/WebCore/ChangeLog	2022-01-07 22:21:03 UTC (rev 287782)
+++ trunk/Source/WebCore/ChangeLog	2022-01-07 22:22:38 UTC (rev 287783)
@@ -1,3 +1,34 @@
+2022-01-07  Kate Cheney  <katherine_che...@apple.com>
+
+        CSP: strict-dynamic is causing incorrect and unexpected behavior
+        https://bugs.webkit.org/show_bug.cgi?id=234756
+        <rdar://problem/87018316>
+
+        Reviewed by Brent Fulgham.
+
+        Per the CSP spec, if strict-dynamic is included in the script-src
+        directive, 'self' and 'unsafe-inline' should be ignored. This fixes a
+        bug where they were only ignored if specified before 'strict-dynamic'.
+
+        Additionally, this reports the sourceURL as empty for inline scripts
+        instead of using the contextURL, which was unexpectedly allowing
+        inline scripts when "self" was used with "strict-dynamic".
+
+        Tests: http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-host-list.html
+               http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-scheme-list.html
+               http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-self.html
+               http/tests/security/contentSecurityPolicy/strict-dynamic-mixed-order-unsafe-inline.html
+
+        * dom/ScriptElement.cpp:
+        (WebCore::ScriptElement::requestClassicScript):
+        (WebCore::ScriptElement::executeClassicScript):
+        * page/csp/ContentSecurityPolicy.cpp:
+        (WebCore::ContentSecurityPolicy::allScriptPoliciesAllow const):
+        (WebCore::ContentSecurityPolicy::allowNonParserInsertedScripts const):
+        * page/csp/ContentSecurityPolicy.h:
+        * page/csp/ContentSecurityPolicySourceList.cpp:
+        (WebCore::ContentSecurityPolicySourceList::parseSource):
+
 2022-01-07  Said Abou-Hallawa  <s...@apple.com>
 
         [GPU Process] Remove the result FilterImage from FilterEffect

Modified: trunk/Source/WebCore/dom/ScriptElement.cpp (287782 => 287783)


--- trunk/Source/WebCore/dom/ScriptElement.cpp	2022-01-07 22:21:03 UTC (rev 287782)
+++ trunk/Source/WebCore/dom/ScriptElement.cpp	2022-01-07 22:22:38 UTC (rev 287783)
@@ -304,7 +304,7 @@
         m_element.document().willLoadScriptElement(scriptURL);
 
         const auto& contentSecurityPolicy = *m_element.document().contentSecurityPolicy();
-        if (!contentSecurityPolicy.allowNonParserInsertedScripts(scriptURL, m_startLineNumber, m_element.nonce(), String(), m_parserInserted))
+        if (!contentSecurityPolicy.allowNonParserInsertedScripts(scriptURL, URL(), m_startLineNumber, m_element.nonce(), String(), m_parserInserted))
             return false;
 
         if (script->load(m_element.document(), scriptURL)) {
@@ -376,7 +376,7 @@
 
     ASSERT(m_element.document().contentSecurityPolicy());
     const auto& contentSecurityPolicy = *m_element.document().contentSecurityPolicy();
-    if (!contentSecurityPolicy.allowNonParserInsertedScripts(m_element.document().url(), m_startLineNumber, m_element.nonce(), sourceCode.source(), m_parserInserted))
+    if (!contentSecurityPolicy.allowNonParserInsertedScripts(URL(), m_element.document().url(), m_startLineNumber, m_element.nonce(), sourceCode.source(), m_parserInserted))
         return false;
 
     bool hasKnownNonce = contentSecurityPolicy.allowScriptWithNonce(nonce, m_element.isInUserAgentShadowTree());
@@ -400,7 +400,7 @@
     if (!m_isExternalScript) {
         ASSERT(m_element.document().contentSecurityPolicy());
         const ContentSecurityPolicy& contentSecurityPolicy = *m_element.document().contentSecurityPolicy();
-        if (!contentSecurityPolicy.allowNonParserInsertedScripts(m_element.document().url(), m_startLineNumber, m_element.nonce(), sourceCode.source(), m_parserInserted))
+        if (!contentSecurityPolicy.allowNonParserInsertedScripts(URL(), m_element.document().url(), m_startLineNumber, m_element.nonce(), sourceCode.source(), m_parserInserted))
             return;
 
         bool hasKnownNonce = contentSecurityPolicy.allowScriptWithNonce(m_element.nonce(), m_element.isInUserAgentShadowTree());

Modified: trunk/Source/WebCore/page/csp/ContentSecurityPolicy.cpp (287782 => 287783)


--- trunk/Source/WebCore/page/csp/ContentSecurityPolicy.cpp	2022-01-07 22:21:03 UTC (rev 287782)
+++ trunk/Source/WebCore/page/csp/ContentSecurityPolicy.cpp	2022-01-07 22:22:38 UTC (rev 287783)
@@ -459,7 +459,7 @@
     return false;
 }
 
-bool ContentSecurityPolicy::allowNonParserInsertedScripts(const URL& url, const OrdinalNumber& contextLine, const String& nonce, const StringView& scriptContent, ParserInserted parserInserted) const
+bool ContentSecurityPolicy::allowNonParserInsertedScripts(const URL& sourceURL, const URL& contextURL, const OrdinalNumber& contextLine, const String& nonce, const StringView& scriptContent, ParserInserted parserInserted) const
 {
     if (!shouldPerformEarlyCSPCheck())
         return true;
@@ -466,11 +466,12 @@
 
     auto handleViolatedDirective = [&] (const ContentSecurityPolicyDirective& violatedDirective) {
         TextPosition sourcePosition(contextLine, OrdinalNumber());
-        String consoleMessage = consoleMessageForViolation(ContentSecurityPolicyDirectiveNames::scriptSrc, violatedDirective, url, "Refused to load");
-        reportViolation(ContentSecurityPolicyDirectiveNames::scriptSrcElem, violatedDirective, url.string(), consoleMessage, String(), scriptContent, sourcePosition);
+        const char* message = sourceURL.isEmpty() ? "Refused to execute a script" : "Refused to load";
+        String consoleMessage = consoleMessageForViolation(ContentSecurityPolicyDirectiveNames::scriptSrc, violatedDirective, sourceURL, message);
+        reportViolation(ContentSecurityPolicyDirectiveNames::scriptSrcElem, violatedDirective, sourceURL.string(), consoleMessage, contextURL.string(), scriptContent, sourcePosition);
     };
 
-    return allScriptPoliciesAllow(handleViolatedDirective, url, nonce, scriptContent, parserInserted);
+    return allScriptPoliciesAllow(handleViolatedDirective, sourceURL, nonce, scriptContent, parserInserted);
 }
 
 bool ContentSecurityPolicy::allowInlineScript(const String& contextURL, const OrdinalNumber& contextLine, StringView scriptContent, Element& element, bool overrideContentSecurityPolicy) const

Modified: trunk/Source/WebCore/page/csp/ContentSecurityPolicy.h (287782 => 287783)


--- trunk/Source/WebCore/page/csp/ContentSecurityPolicy.h	2022-01-07 22:21:03 UTC (rev 287782)
+++ trunk/Source/WebCore/page/csp/ContentSecurityPolicy.h	2022-01-07 22:22:38 UTC (rev 287783)
@@ -101,7 +101,7 @@
     bool allowJavaScriptURLs(const String& contextURL, const OrdinalNumber& contextLine, const String& code, bool overrideContentSecurityPolicy = false) const;
     bool allowInlineEventHandlers(const String& contextURL, const OrdinalNumber& contextLine, const String& code, Element*, bool overrideContentSecurityPolicy = false) const;
     bool allowInlineScript(const String& contextURL, const OrdinalNumber& contextLine, StringView scriptContent, Element&, bool overrideContentSecurityPolicy = false) const;
-    bool allowNonParserInsertedScripts(const URL&, const OrdinalNumber&, const String&, const StringView&, ParserInserted) const;
+    bool allowNonParserInsertedScripts(const URL& sourceURL, const URL& contextURL, const OrdinalNumber&, const String&, const StringView&, ParserInserted) const;
     bool allowInlineStyle(const String& contextURL, const OrdinalNumber& contextLine, StringView styleContent, CheckUnsafeHashes, Element&, bool overrideContentSecurityPolicy = false) const;
 
     bool allowEval(JSC::JSGlobalObject*, LogToConsole, StringView codeContent, bool overrideContentSecurityPolicy = false) const;

Modified: trunk/Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp (287782 => 287783)


--- trunk/Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp	2022-01-07 22:21:03 UTC (rev 287782)
+++ trunk/Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp	2022-01-07 22:22:38 UTC (rev 287783)
@@ -234,7 +234,7 @@
         return source;
     }
 
-    if (skipExactlyIgnoringASCIICase(buffer, "'strict-dynamic'")) {
+    if (skipExactlyIgnoringASCIICase(buffer, "'strict-dynamic'") && (m_directiveName == ContentSecurityPolicyDirectiveNames::scriptSrc || m_directiveName == ContentSecurityPolicyDirectiveNames::scriptSrcElem)) {
         m_allowNonParserInsertedScripts = true;
         m_allowSelf = false;
         m_allowInline = false;
@@ -242,12 +242,12 @@
     }
 
     if (skipExactlyIgnoringASCIICase(buffer, "'self'")) {
-        m_allowSelf = true;
+        m_allowSelf = !m_allowNonParserInsertedScripts;
         return source;
     }
 
     if (skipExactlyIgnoringASCIICase(buffer, "'unsafe-inline'")) {
-        m_allowInline = true;
+        m_allowInline = !m_allowNonParserInsertedScripts;
         return source;
     }
 
@@ -266,6 +266,9 @@
         return source;
     }
 
+    if (m_allowNonParserInsertedScripts)
+        return source;
+
     auto begin = buffer.position();
     auto beginHost = begin;
     auto beginPath = buffer.end();
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to