- 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();