chore: cherry-pick 2ef09109c0ec from chromium (#36591)

Co-authored-by: electron-patch-conflict-fixer[bot] <83340002+electron-patch-conflict-fixer[bot]@users.noreply.github.com>
This commit is contained in:
Pedro Pontes
2022-12-09 12:27:30 +01:00
committed by GitHub
parent 5abed6e890
commit c9e67c38b7
2 changed files with 365 additions and 0 deletions

View File

@@ -128,4 +128,5 @@ fix_on-screen-keyboard_hides_on_input_blur_in_webview.patch
build_allow_electron_to_use_exec_script.patch
cherry-pick-67c9cbc784d6.patch
cherry-pick-933cc81c6bad.patch
cherry-pick-2ef09109c0ec.patch
cherry-pick-f98adc846aad.patch

View File

@@ -0,0 +1,364 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jun Kokatsu <jkokatsu@google.com>
Date: Thu, 22 Sep 2022 22:16:55 +0000
Subject: Unify security check for Javascript URL navigation
This change unifies CSP and Trusted Types check for Javascript URL
navigations.
Bug: 1365082
Change-Id: I46aea31a918c6397ea71fd5ab345bc9dc19d91c2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3905476
Auto-Submit: Jun Kokatsu <jkokatsu@google.com>
Commit-Queue: Jun Kokatsu <jkokatsu@google.com>
Reviewed-by: Nate Chapin <japhet@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1050416}
diff --git a/third_party/blink/renderer/bindings/core/v8/script_controller.cc b/third_party/blink/renderer/bindings/core/v8/script_controller.cc
index 0a978ee553cd3bf4b15b923fbf8b93789c441774..1a79fa26c069d10e9e03390f161d70d2adb7b07e 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_controller.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_controller.cc
@@ -200,34 +200,9 @@ void ScriptController::ExecuteJavaScriptURL(
const DOMWrapperWorld* world_for_csp) {
DCHECK(url.ProtocolIsJavaScript());
- const int kJavascriptSchemeLength = sizeof("javascript:") - 1;
- String script_source = DecodeURLEscapeSequences(
- url.GetString(), DecodeURLMode::kUTF8OrIsomorphic);
-
if (!window_->GetFrame())
return;
- auto* policy = window_->GetContentSecurityPolicyForWorld(world_for_csp);
- if (csp_disposition == network::mojom::CSPDisposition::CHECK &&
- !policy->AllowInline(ContentSecurityPolicy::InlineType::kNavigation,
- nullptr, script_source, String() /* nonce */,
- window_->Url(), EventHandlerPosition().line_)) {
- return;
- }
-
- // TODO(crbug.com/896041): Investigate how trusted type checks can be
- // implemented for isolated worlds.
- const bool should_bypass_trusted_type_check =
- csp_disposition == network::mojom::CSPDisposition::DO_NOT_CHECK ||
- ContentSecurityPolicy::ShouldBypassMainWorldDeprecated(world_for_csp);
- script_source = script_source.Substring(kJavascriptSchemeLength);
- if (!should_bypass_trusted_type_check) {
- script_source = TrustedTypesCheckForJavascriptURLinNavigation(
- script_source, window_.Get());
- if (script_source.IsEmpty())
- return;
- }
-
bool had_navigation_before =
window_->GetFrame()->Loader().HasProvisionalNavigation();
@@ -235,6 +210,9 @@ void ScriptController::ExecuteJavaScriptURL(
// Step 6. "Let baseURL be settings's API base URL." [spec text]
const KURL base_url = window_->BaseURL();
+ String script_source = window_->CheckAndGetJavascriptUrl(
+ world_for_csp, url, nullptr /* element */, csp_disposition);
+
// Step 7. "Let script be the result of creating a classic script given
// scriptSource, settings, baseURL, and the default classic script fetch
// options." [spec text]
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index c4be7a96144ac53be856fbf52dff8e990aa736aa..12183222040fd9ab3e202a510cc71f2ccbf2e4c4 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -418,6 +418,39 @@ bool LocalDOMWindow::CanExecuteScripts(
return script_enabled;
}
+String LocalDOMWindow::CheckAndGetJavascriptUrl(
+ const DOMWrapperWorld* world,
+ const KURL& url,
+ Element* element,
+ network::mojom::CSPDisposition csp_disposition) {
+ const int kJavascriptSchemeLength = sizeof("javascript:") - 1;
+ String decoded_url = DecodeURLEscapeSequences(
+ url.GetString(), DecodeURLMode::kUTF8OrIsomorphic);
+ String script_source = decoded_url.Substring(kJavascriptSchemeLength);
+
+ if (csp_disposition == network::mojom::CSPDisposition::DO_NOT_CHECK)
+ return script_source;
+
+ // Check the CSP of the caller (the "source browsing context") if required,
+ // as per https://html.spec.whatwg.org/C/#javascript-protocol.
+ if (!GetContentSecurityPolicyForWorld(world)->AllowInline(
+ ContentSecurityPolicy::InlineType::kNavigation, element, decoded_url,
+ String() /* nonce */, Url(), OrdinalNumber::First()))
+ return String();
+
+ // TODO(crbug.com/896041): Investigate how trusted type checks can be
+ // implemented for isolated worlds.
+ if (ContentSecurityPolicy::ShouldBypassMainWorldDeprecated(world))
+ return script_source;
+
+ // https://w3c.github.io/webappsec-trusted-types/dist/spec/#require-trusted-types-for-pre-navigation-check
+ // 4.9.1.1. require-trusted-types-for Pre-Navigation check
+ script_source =
+ TrustedTypesCheckForJavascriptURLinNavigation(script_source, this);
+
+ return script_source;
+}
+
void LocalDOMWindow::ExceptionThrown(ErrorEvent* event) {
MainThreadDebugger::Instance()->ExceptionThrown(this, event);
}
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.h b/third_party/blink/renderer/core/frame/local_dom_window.h
index 7091b979bed2c3ee375453ebc68aa83102745f35..b485bb1a08bc58bc1738c97c0311dc2d47d233e2 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.h
+++ b/third_party/blink/renderer/core/frame/local_dom_window.h
@@ -31,6 +31,7 @@
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "services/network/public/mojom/content_security_policy.mojom-blink.h"
#include "third_party/blink/public/common/frame/fullscreen_request_token.h"
#include "third_party/blink/public/common/frame/payment_request_token.h"
#include "third_party/blink/public/common/metrics/post_message_counter.h"
@@ -215,6 +216,16 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
mojom::blink::PermissionsPolicyFeature feature,
UseCounterImpl::PermissionsPolicyUsageType type);
+ // Checks if navigation to Javascript URL is allowed. This check should run
+ // before any action is taken (e.g. creating new window) for all
+ // same-origin navigations.
+ String CheckAndGetJavascriptUrl(
+ const DOMWrapperWorld* world,
+ const KURL& url,
+ Element* element,
+ network::mojom::CSPDisposition csp_disposition =
+ network::mojom::CSPDisposition::CHECK);
+
Document* InstallNewDocument(const DocumentInit&);
// EventTarget overrides:
diff --git a/third_party/blink/renderer/core/frame/location.cc b/third_party/blink/renderer/core/frame/location.cc
index a1aeede568cfe33267d87fa68f096d20a83d50f9..92740842827d470d63da34dd90bdb937321c1a83 100644
--- a/third_party/blink/renderer/core/frame/location.cc
+++ b/third_party/blink/renderer/core/frame/location.cc
@@ -270,23 +270,6 @@ void Location::SetLocation(const String& url,
return;
}
- // Check the source browsing context's CSP to fulfill the CSP check
- // requirement of https://html.spec.whatwg.org/C/#navigate for javascript
- // URLs. Although the spec states we should perform this check on task
- // execution, there are concerns about the correctness of that statement,
- // see http://github.com/whatwg/html/issues/2591.
- if (completed_url.ProtocolIsJavaScript()) {
- String script_source = DecodeURLEscapeSequences(
- completed_url.GetString(), DecodeURLMode::kUTF8OrIsomorphic);
- if (!incumbent_window->GetContentSecurityPolicyForCurrentWorld()
- ->AllowInline(ContentSecurityPolicy::InlineType::kNavigation,
- nullptr /* element */, script_source,
- String() /* nonce */, incumbent_window->Url(),
- OrdinalNumber::First())) {
- return;
- }
- }
-
V8DOMActivityLogger* activity_logger =
V8DOMActivityLogger::CurrentActivityLoggerIfIsolatedWorld();
if (activity_logger) {
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index 4786257911cd9cb01222ef375698e0ae669d8ccb..94e04ff48d7a395cd673a9ececd598d00e735ff5 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -537,19 +537,12 @@ bool FrameLoader::AllowRequestForThisFrame(const FrameLoadRequest& request) {
const KURL& url = request.GetResourceRequest().Url();
if (url.ProtocolIsJavaScript()) {
- // Check the CSP of the caller (the "source browsing context") if required,
- // as per https://html.spec.whatwg.org/C/#javascript-protocol.
- bool javascript_url_is_allowed =
- request.GetOriginWindow()
- ->GetContentSecurityPolicyForWorld(request.JavascriptWorld().get())
- ->AllowInline(ContentSecurityPolicy::InlineType::kNavigation,
- frame_->DeprecatedLocalOwner(), url.GetString(),
- String() /* nonce */,
- request.GetOriginWindow()->Url(),
- OrdinalNumber::First());
-
- if (!javascript_url_is_allowed)
+ if (request.GetOriginWindow()
+ ->CheckAndGetJavascriptUrl(request.JavascriptWorld().get(), url,
+ frame_->DeprecatedLocalOwner())
+ .IsEmpty()) {
return false;
+ }
if (frame_->Owner() && ((frame_->Owner()->GetFramePolicy().sandbox_flags &
network::mojom::blink::WebSandboxFlags::kOrigin) !=
diff --git a/third_party/blink/renderer/core/page/create_window.cc b/third_party/blink/renderer/core/page/create_window.cc
index 7e73ad64a9b28396473adefaefd6430f81e61011..118ca880ffba6cc96a51b7b083119bd41f990e15 100644
--- a/third_party/blink/renderer/core/page/create_window.cc
+++ b/third_party/blink/renderer/core/page/create_window.cc
@@ -294,15 +294,11 @@ Frame* CreateNewWindow(LocalFrame& opener_frame,
request.SetFrameType(mojom::RequestContextFrameType::kAuxiliary);
const KURL& url = request.GetResourceRequest().Url();
- auto* csp_for_world = opener_window.GetContentSecurityPolicyForCurrentWorld();
- if (url.ProtocolIsJavaScript() && csp_for_world) {
- String script_source = DecodeURLEscapeSequences(
- url.GetString(), DecodeURLMode::kUTF8OrIsomorphic);
-
- if (!csp_for_world->AllowInline(
- ContentSecurityPolicy::InlineType::kNavigation,
- nullptr /* element */, script_source, String() /* nonce */,
- opener_window.Url(), OrdinalNumber::First())) {
+ if (url.ProtocolIsJavaScript()) {
+ if (opener_window
+ .CheckAndGetJavascriptUrl(request.JavascriptWorld().get(), url,
+ nullptr /* element */)
+ .IsEmpty()) {
return nullptr;
}
}
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/support/frame-without-trusted-types.html b/third_party/blink/web_tests/external/wpt/trusted-types/support/frame-without-trusted-types.html
new file mode 100644
index 0000000000000000000000000000000000000000..25cf073e79fa48f4311c3729f0b39d9be2a64e7c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/support/frame-without-trusted-types.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<head>
+</head>
+<body>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-report-only-support.html b/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-report-only-support.html
index d00d0538753a74411feeec42d5682082031c09d4..5f7856fabb7bb16085ffaffffbf6d7553179e8f3 100644
--- a/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-report-only-support.html
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-report-only-support.html
@@ -5,7 +5,8 @@
<p>Support page for trusted-types-navigation-report-only.*.html tests.</p>
<a id="anchor" href="#">link</a>
<script>
- if (location.search == "?defaultpolicy") {
+ const params = new URLSearchParams(location.search);
+ if (!!params.get("defaultpolicy")) {
trustedTypes.createPolicy("default", {
createScript: s => s.replace("continue", "defaultpolicywashere"),
});
@@ -36,9 +37,17 @@
// won't disturb delivery of that event to the opener.
const anchor = document.getElementById("anchor");
anchor.href = target;
+
+ if (!!params.get("frame")) {
+ const frame = document.createElement("iframe");
+ frame.src = "frame-without-trusted-types.html";
+ frames.name = "frame";
+ document.body.appendChild(frame);
+ anchor.target = "frame";
+ }
+
if (!location.hash) {
document.addEventListener("DOMContentLoaded", _ => anchor.click());
}
</script>
</body>
-
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-support.html b/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-support.html
index cd41f3968e7c74f84a7541506053808073ce541d..5e02e6d4bf5aff9fa4f0b4b897a35726ed24168b 100644
--- a/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-support.html
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-support.html
@@ -5,7 +5,8 @@
<p>Support page for trusted-types-navigation.*.html tests.</p>
<a id="anchor" href="#">link</a>
<script>
- if (location.search == "?defaultpolicy") {
+ const params = new URLSearchParams(location.search);
+ if (!!params.get("defaultpolicy")) {
trustedTypes.createPolicy("default", {
createScript: s => s.replace("continue", "defaultpolicywashere"),
});
@@ -35,8 +36,16 @@
const anchor = document.getElementById("anchor");
anchor.href = target;
+
+ if (!!params.get("frame")) {
+ const frame = document.createElement("iframe");
+ frame.src = "frame-without-trusted-types.html";
+ frames.name = "frame";
+ document.body.appendChild(frame);
+ anchor.target = "frame";
+ }
+
if (!location.hash)
document.addEventListener("DOMContentLoaded", _ => anchor.click());
</script>
</body>
-
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-navigation.tentative.html b/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-navigation.tentative.html
index 4e784611dd64ecf2f9995403b1d4e5a19f8b4548..2113711902ae787cb3ad5d0e44eaed0fc2e99b87 100644
--- a/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-navigation.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-navigation.tentative.html
@@ -38,10 +38,10 @@
}, "Navigate a window with javascript:-urls in enforcing mode.");
promise_test(t => {
- openWindow(t, "support/navigation-support.html?defaultpolicy");
+ openWindow(t, "support/navigation-support.html?defaultpolicy=1");
return Promise.all([
- expectLoadedAsMessage("navigation-support.html?defaultpolicy"),
- expectLoadedAsMessage("navigation-support.html?defaultpolicy&defaultpolicywashere"),
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1"),
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1&defaultpolicywashere"),
]);
}, "Navigate a window with javascript:-urls w/ default policy in enforcing mode.");
@@ -55,12 +55,46 @@
}, "Navigate a window with javascript:-urls in report-only mode.");
promise_test(t => {
- const page = "navigation-report-only-support.html?defaultpolicy";
+ const page = "navigation-report-only-support.html?defaultpolicy=1";
openWindow(t, `support/${page}`);
return Promise.all([
expectLoadedAsMessage(page),
- expectLoadedAsMessage("navigation-support.html?defaultpolicy#defaultpolicywashere"),
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1#defaultpolicywashere"),
]);
}, "Navigate a window with javascript:-urls w/ default policy in report-only mode.");
+
+ promise_test(t => {
+ openWindow(t, "support/navigation-support.html?frame=1");
+ return Promise.all([
+ expectLoadedAsMessage("navigation-support.html?frame=1"),
+ expectViolationAsMessage("Location href"),
+ ]);
+ }, "Navigate a frame with javascript:-urls in enforcing mode.");
+
+ promise_test(t => {
+ openWindow(t, "support/navigation-support.html?defaultpolicy=1&frame=1");
+ return Promise.all([
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1&frame=1"),
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1&frame=1&defaultpolicywashere"),
+ ]);
+ }, "Navigate a frame with javascript:-urls w/ default policy in enforcing mode.");
+
+ promise_test(t => {
+ const page = "navigation-report-only-support.html?frame=1"
+ openWindow(t, `support/${page}`);
+ return Promise.all([
+ expectLoadedAsMessage(page),
+ expectLoadedAsMessage("navigation-support.html?frame=1#continue"),
+ ]);
+ }, "Navigate a frame with javascript:-urls in report-only mode.");
+
+ promise_test(t => {
+ const page = "navigation-report-only-support.html?defaultpolicy=1&frame=1";
+ openWindow(t, `support/${page}`);
+ return Promise.all([
+ expectLoadedAsMessage(page),
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1&frame=1#defaultpolicywashere"),
+ ]);
+ }, "Navigate a frame with javascript:-urls w/ default policy in report-only mode.");
</script>
</body>