Title: [290853] trunk
Revision
290853
Author
katherine_che...@apple.com
Date
2022-03-04 15:45:03 -0800 (Fri, 04 Mar 2022)

Log Message

about:blank iframes do not always inherit parent CSP
https://bugs.webkit.org/show_bug.cgi?id=236347
<rdar://problem/88669147>

Reviewed by Brent Fulgham.

Source/WebCore:

Test: http/tests/security/contentSecurityPolicy/block-eval-onload-in-nested-about-blank-iframe.html

Usually we initialize CSP for window when we create a jsWindowProxy
for that frame. In this case, we load an about:blank iframe that
attempts to run eval() in the onload function of its own nested
iframe. Since we never run script in frame, we don't initialize a
jsWindowProxy and thus never propogate its CSP.

This fix checks the document's CSP in FrameLoader::clear when we
initialize a new JSGlobalObject and sets the eval value in the window
accordingly to properly enforce CSP.

* bindings/js/ScriptController.cpp:
(WebCore::ScriptController::enableEval):
* bindings/js/ScriptController.h:
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::clear):
* page/csp/ContentSecurityPolicy.h:
(WebCore::ContentSecurityPolicy::evalErrorMessage const):

LayoutTests:

* http/tests/security/contentSecurityPolicy/block-eval-onload-in-nested-about-blank-iframe-expected.txt: Added.
* http/tests/security/contentSecurityPolicy/block-eval-onload-in-nested-about-blank-iframe.html: Added
We can't use modern js-test.js and related functions because
js-test.js uses eval() and loading it makes the test time out when the
eval is blocked by the document's CSP. We can't specify unsafe-eval
because the whole point of this test is to block eval.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (290852 => 290853)


--- trunk/LayoutTests/ChangeLog	2022-03-04 23:31:23 UTC (rev 290852)
+++ trunk/LayoutTests/ChangeLog	2022-03-04 23:45:03 UTC (rev 290853)
@@ -1,3 +1,18 @@
+2022-03-04  Kate Cheney  <katherine_che...@apple.com>
+
+        about:blank iframes do not always inherit parent CSP
+        https://bugs.webkit.org/show_bug.cgi?id=236347
+        <rdar://problem/88669147>
+
+        Reviewed by Brent Fulgham.
+
+        * http/tests/security/contentSecurityPolicy/block-eval-onload-in-nested-about-blank-iframe-expected.txt: Added.
+        * http/tests/security/contentSecurityPolicy/block-eval-onload-in-nested-about-blank-iframe.html: Added
+        We can't use modern js-test.js and related functions because
+        js-test.js uses eval() and loading it makes the test time out when the
+        eval is blocked by the document's CSP. We can't specify unsafe-eval
+        because the whole point of this test is to block eval.
+
 2022-03-04  Robert Jenner  <jen...@apple.com>
 
         Update WPT css-scroll-snap tests

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/block-eval-onload-in-nested-about-blank-iframe-expected.txt (0 => 290853)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/block-eval-onload-in-nested-about-blank-iframe-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/block-eval-onload-in-nested-about-blank-iframe-expected.txt	2022-03-04 23:45:03 UTC (rev 290853)
@@ -0,0 +1,5 @@
+CONSOLE MESSAGE: EvalError: Refused to evaluate a string as _javascript_ because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self' 'unsafe-inline'".
+
+Tests that nested about:blank iframes that try to eval on load inherit the parent's CSP
+
+

Added: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/block-eval-onload-in-nested-about-blank-iframe.html (0 => 290853)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/block-eval-onload-in-nested-about-blank-iframe.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/block-eval-onload-in-nested-about-blank-iframe.html	2022-03-04 23:45:03 UTC (rev 290853)
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<head>
+    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'">
+</head>
+<p>Tests that nested about:blank iframes that try to eval on load inherit the parent's CSP</p>
+<body>
+    <iframe id=x src=""
+    <script>
+        testRunner.waitUntilDone();
+        testRunner.dumpAsText();
+
+        x._onload_=_=> {
+            x.contentDocument.body.innerHTML= "<iframe _onload_='eval(`alert(1)`)'><\/iframe>";
+            testRunner.notifyDone();
+        }
+        x.contentWindow.location.reload();
+    </script>
+</body>
+

Modified: trunk/Source/WebCore/ChangeLog (290852 => 290853)


--- trunk/Source/WebCore/ChangeLog	2022-03-04 23:31:23 UTC (rev 290852)
+++ trunk/Source/WebCore/ChangeLog	2022-03-04 23:45:03 UTC (rev 290853)
@@ -1,3 +1,31 @@
+2022-03-04  Kate Cheney  <katherine_che...@apple.com>
+
+        about:blank iframes do not always inherit parent CSP
+        https://bugs.webkit.org/show_bug.cgi?id=236347
+        <rdar://problem/88669147>
+
+        Reviewed by Brent Fulgham.
+
+        Test: http/tests/security/contentSecurityPolicy/block-eval-onload-in-nested-about-blank-iframe.html
+
+        Usually we initialize CSP for window when we create a jsWindowProxy
+        for that frame. In this case, we load an about:blank iframe that
+        attempts to run eval() in the onload function of its own nested
+        iframe. Since we never run script in frame, we don't initialize a
+        jsWindowProxy and thus never propogate its CSP.
+
+        This fix checks the document's CSP in FrameLoader::clear when we
+        initialize a new JSGlobalObject and sets the eval value in the window
+        accordingly to properly enforce CSP.
+
+        * bindings/js/ScriptController.cpp:
+        (WebCore::ScriptController::enableEval):
+        * bindings/js/ScriptController.h:
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::clear):
+        * page/csp/ContentSecurityPolicy.h:
+        (WebCore::ContentSecurityPolicy::evalErrorMessage const):
+
 2022-03-04  Myles C. Maxfield  <mmaxfi...@apple.com>
 
         [iOS] Books ASSERTs upon opening a book with a debug build of WebKit

Modified: trunk/Source/WebCore/bindings/js/ScriptController.cpp (290852 => 290853)


--- trunk/Source/WebCore/bindings/js/ScriptController.cpp	2022-03-04 23:31:23 UTC (rev 290852)
+++ trunk/Source/WebCore/bindings/js/ScriptController.cpp	2022-03-04 23:45:03 UTC (rev 290853)
@@ -406,12 +406,12 @@
     return TextPosition();
 }
 
-void ScriptController::enableEval()
+void ScriptController::enableEval(bool enable, const String& errorMessage)
 {
     auto* jsWindowProxy = windowProxy().existingJSWindowProxy(mainThreadNormalWorld());
     if (!jsWindowProxy)
         return;
-    jsWindowProxy->window()->setEvalEnabled(true);
+    jsWindowProxy->window()->setEvalEnabled(enable, errorMessage);
 }
 
 void ScriptController::enableWebAssembly()

Modified: trunk/Source/WebCore/bindings/js/ScriptController.h (290852 => 290853)


--- trunk/Source/WebCore/bindings/js/ScriptController.h	2022-03-04 23:31:23 UTC (rev 290852)
+++ trunk/Source/WebCore/bindings/js/ScriptController.h	2022-03-04 23:45:03 UTC (rev 290853)
@@ -124,7 +124,7 @@
 
     TextPosition eventHandlerPosition() const;
 
-    void enableEval();
+    void enableEval(bool, const String& errorMessage = String());
     void enableWebAssembly();
     void disableEval(const String& errorMessage);
     void disableWebAssembly(const String& errorMessage);

Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (290852 => 290853)


--- trunk/Source/WebCore/loader/FrameLoader.cpp	2022-03-04 23:31:23 UTC (rev 290852)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp	2022-03-04 23:45:03 UTC (rev 290853)
@@ -667,7 +667,10 @@
     if (clearScriptObjects)
         m_frame.script().clearScriptObjects();
 
-    m_frame.script().enableEval();
+    if (newDocument->contentSecurityPolicy() && !newDocument->contentSecurityPolicy()->evalErrorMessage().isNull())
+        m_frame.script().enableEval(false, newDocument->contentSecurityPolicy()->evalErrorMessage());
+    else
+        m_frame.script().enableEval(true);
 
     m_frame.navigationScheduler().clear();
 

Modified: trunk/Source/WebCore/page/csp/ContentSecurityPolicy.h (290852 => 290853)


--- trunk/Source/WebCore/page/csp/ContentSecurityPolicy.h	2022-03-04 23:31:23 UTC (rev 290852)
+++ trunk/Source/WebCore/page/csp/ContentSecurityPolicy.h	2022-03-04 23:45:03 UTC (rev 290853)
@@ -191,6 +191,8 @@
 
     bool isHeaderDelivered() const { return m_isHeaderDelivered; }
 
+    const String& evalErrorMessage() const { return m_lastPolicyEvalDisabledErrorMessage; }
+
 private:
     void logToConsole(const String& message, const String& contextURL = String(), const OrdinalNumber& contextLine = OrdinalNumber::beforeFirst(), const OrdinalNumber& contextColumn = OrdinalNumber::beforeFirst(), JSC::JSGlobalObject* = nullptr) const;
     void applyPolicyToScriptExecutionContext();
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to