Anchor target=_blank implies rel=noopener
To mitigate "tab-napping" attacks, in which a new tab/window opened by
a victim context may navigate that opener context, the HTML standard
changed to specify that anchors that target _blank should behave as if
|rel="noopener"| is set. A page wishing to opt out of this behavior may
set |rel="opener"|.
Bug: 898942
Change-Id: Id34bbc480e96cb2cc8e922388a9a5bc4161b03b1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1630010
Reviewed-by: Julian Pastarmov <[email protected]>
Reviewed-by: John Abd-El-Malek <[email protected]>
Reviewed-by: Marijn Kruisselbrink <[email protected]>
Reviewed-by: Mike West <[email protected]>
Reviewed-by: Arthur Sonzogni <[email protected]>
Commit-Queue: Eric Lawrence [MSFT] <[email protected]>
Cr-Commit-Position: refs/heads/master@{#825022}
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index f140422..c7e9d29 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2326,6 +2326,12 @@
blink::switches::kUserAgentClientHintDisable);
}
+ if (!local_state->GetBoolean(
+ policy::policy_prefs::kTargetBlankImpliesNoOpener)) {
+ command_line->AppendSwitch(
+ switches::kDisableTargetBlankImpliesNoOpener);
+ }
+
#if defined(OS_ANDROID)
// Communicating to content/ for BackForwardCache.
if (prefs->HasPrefPath(policy::policy_prefs::kBackForwardCacheEnabled) &&
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index b4bd7c6..90debc9 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -1300,6 +1300,9 @@
{ key::kLookalikeWarningAllowlistDomains,
prefs::kLookalikeWarningAllowlistDomains,
base::Value::Type::LIST },
+ { key::kTargetBlankImpliesNoOpener,
+ policy::policy_prefs::kTargetBlankImpliesNoOpener,
+ base::Value::Type::BOOLEAN },
#if defined(OS_ANDROID)
{ key::kTosDialogBehavior,
diff --git a/chrome/browser/policy/window_opener_policy_browsertest.cc b/chrome/browser/policy/window_opener_policy_browsertest.cc
new file mode 100644
index 0000000..3cbf1ac
--- /dev/null
+++ b/chrome/browser/policy/window_opener_policy_browsertest.cc
@@ -0,0 +1,71 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// TODO(crbug.com/898942): Remove this in Chrome 95.
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/policy/policy_test_utils.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/core/common/policy_pref_names.h"
+#include "components/policy/core/common/policy_types.h"
+#include "components/policy/policy_constants.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace policy {
+
+class PolicyTestWindowOpener : public PolicyTest {
+ void SetUpInProcessBrowserTestFixture() override {
+ PolicyTest::SetUpInProcessBrowserTestFixture();
+ PolicyMap policies;
+ // Configure the policy to disable the new behavior.
+ SetPolicy(&policies, policy::key::kTargetBlankImpliesNoOpener,
+ base::Value(false));
+ provider_.UpdateChromePolicy(policies);
+ }
+};
+
+// Check that when the TargetBlankImpliesNoOpener policy is configured and set
+// to false, windows targeting _blank do not have their opener cleared.
+IN_PROC_BROWSER_TEST_F(PolicyTestWindowOpener, CheckWindowOpenerNonNull) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ PrefService* local_state = g_browser_process->local_state();
+ EXPECT_FALSE(local_state->GetBoolean(
+ policy::policy_prefs::kTargetBlankImpliesNoOpener));
+
+ GURL url(
+ "data:text/html,<a href='about:blank' target='_blank' "
+ "id='link'>popup</a>");
+ ui_test_utils::NavigateToURL(browser(), url);
+
+ ASSERT_EQ(browser()->tab_strip_model()->count(), 1);
+ content::WebContents* tab_1 =
+ browser()->tab_strip_model()->GetActiveWebContents();
+
+ ui_test_utils::TabAddedWaiter tab_Added_waiter(browser());
+ SimulateMouseClickOrTapElementWithId(tab_1, "link");
+ tab_Added_waiter.Wait();
+ content::WebContents* tab_2 =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ ASSERT_NE(tab_1, tab_2);
+
+ constexpr char kScript[] =
+ R"({ window.domAutomationController.send(window.opener === null); })";
+ content::ExecuteScriptAsync(tab_2, kScript);
+
+ content::DOMMessageQueue message_queue;
+ std::string message;
+ EXPECT_TRUE(message_queue.WaitForMessage(&message));
+ EXPECT_EQ("false", message);
+}
+
+} // namespace policy
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 43fe63e..b1817554 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -604,6 +604,8 @@
policy::policy_prefs::kIntensiveWakeUpThrottlingEnabled, false);
registry->RegisterBooleanPref(
policy::policy_prefs::kUserAgentClientHintsEnabled, true);
+ registry->RegisterBooleanPref(
+ policy::policy_prefs::kTargetBlankImpliesNoOpener, true);
#if defined(OS_ANDROID)
registry->RegisterBooleanPref(policy::policy_prefs::kBackForwardCacheEnabled,
true);