Chrome · WebProtect › Data Controls
CVE-2026-113299
Memory Corruption in WebProtect (Data Controls)
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifchrome/browser/enterprise/data_protection/data_protection_clipboard_utils.cc |
modified |
Files Changed
chrome/browser/enterprise/data_protection/data_protection_clipboard_utils_unittest.ccchrome/browser/enterprise/data_protection/data_protection_clipboard_utils.ccchrome/browser/enterprise/data_protection/print_utils.ccchrome/browser/enterprise/data_protection/data_protection_utils.hchrome/browser/enterprise/data_protection/data_protection_clipboard_utils_types.ccchrome/browser/enterprise/BUILD.gncontent/public/browser/clipboard_types.ccchrome/browser/enterprise/data_protection/data_protection_utils.ccchrome/browser/enterprise/data_protection/data_protection_navigation_observer.ccchrome/browser/enterprise/data_protection/data_protection_clipboard_utils.h
Patch
From fc9908e21ed6bdeb36c6ea8b4bacef92357aa231 Mon Sep 17 00:00:00 2001 From: Dominique Fauteux-Chapleau <[email protected]> Date: Thu, 24 Sep 2026 12:12:18 -0700 Subject: [PATCH] [Data Controls] Use precursor origin URL for blank/uncommitted frames When a popup is opened with a non-committing URL such as `window.open("javascript:void(0)")`, the popup remains on its initial empty document and `RenderFrameHost::GetLastCommittedURL()` returns an empty/invalid `GURL`. Similarly, `window.open("about:blank")` commits `about:blank` as its URL while inheriting the opener's security origin. Because Data Controls and Enterprise Connectors checks relied solely on `GetLastCommittedURL()`, popups on an initial empty document or `about:blank` could bypass site-specific rules (e.g. `urls: ["source.com"]`) as well as wildcard rules (`urls: ["*"]`, since `url_matcher::URLMatcher` does not match invalid `GURL`s and `CreateDataEndpoint()` returned `std::nullopt` before invoking `MaybeOverrideSourceURLForClipboardAccess()`). This CL: 1. Introduces a shared `GetUrlFromRenderFrameHost()` helper in `enterprise_data_protection` that resolves the main frame's last committed URL, falling back to `GetLastCommittedOrigin().GetTupleOrPrecursorTupleIfOpaque().GetURL()` (or `about:blank` when no valid origin tuple exists) when the committed URL is invalid, `about:blank`, or `about:srcdoc`. 2. Updates `MaybeOverrideSourceURLForClipboardAccess()`, `DataProtectionNavigationObserver::ApplyDataProtectionSettings()`, and `GetPrintAnalysisData()` to use `GetUrlFromRenderFrameHost()`. 3. Moves the `!source_url.is_valid()` check in `content::CreateDataEndpoint()` to run after `MaybeOverrideSourceURLForClipboardAccess()` so uncommitted documents can still receive an overridden `DataTransferEndpoint` URL. Fixed: 532987588 Change-Id: I7726712b0d6ed51f38b9fe51db56ef00d7db439e Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8424128 Reviewed-by: Avi Drissman <[email protected]> Auto-Submit: Dominique Fauteux-Chapleau <[email protected]> Commit-Queue: Avi Drissman <[email protected]> Commit-Queue: Dominique Fauteux-Chapleau <[email protected]> Cr-Commit-Position: refs/heads/main@{#1704494} --- diff --git a/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils.cc b/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils.cc index bb419ed..66938bba 100644 --- a/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils.cc +++ b/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils.cc @@ -24,9 +24,9 @@ #include "chrome/browser/enterprise/data_controls/chrome_clipboard_context.h" #include "chrome/browser/enterprise/data_controls/chrome_rules_service.h" #include "chrome/browser/enterprise/data_controls/data_controls_dialog_factory.h" +#include "chrome/browser/enterprise/data_protection/data_protection_utils.h" #include "chrome/browser/enterprise/data_protection/paste_allowed_request.h" #include "chrome/browser/profiles/profile.h" -#include "components/dom_distiller/core/url_utils.h" #include "components/enterprise/common/files_scan_data.h" #include "components/enterprise/connectors/core/connectors_prefs.h" #include "components/enterprise/connectors/core/features.h" @@ -56,6 +56,7 @@ #include "ui/base/data_transfer_policy/data_transfer_policy_controller.h" #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" +#include "url/url_constants.h" #if BUILDFLAG(ENABLE_PRINT_PREVIEW) #include "chrome/browser/printing/print_preview_dialog_controller.h" @@ -95,19 +96,14 @@ if (!endpoint.data_transfer_endpoint() || !endpoint.data_transfer_endpoint()->IsUrlType() || !endpoint.data_transfer_endpoint()->GetURL()) { + if (endpoint.render_frame_host()) { + return GetUrlFromRenderFrameHost(endpoint.render_frame_host()); + } return GURL(); } return *endpoint.data_transfer_endpoint()->GetURL(); } -GURL GetSourceURL(content::RenderFrameHost* rfh) { - auto url = rfh->GetMainFrame()->GetLastCommittedURL(); - if (dom_distiller::url_utils::IsDistilledPage(url)) { - url = dom_distiller::url_utils::GetOriginalUrlFromDistillerUrl(url); - } - return url; -} - bool SkipDataControlOrContentAnalysisChecks( const content::ClipboardEndpoint& main_endpoint) { // Data Controls and content analysis copy/paste checks require an active tab @@ -405,11 +401,11 @@ Profile::FromBrowserContext(destination->GetBrowserContext())) { email = enterprise_connectors::ContentAreaUserProvider::GetUser( profile, content::WebContents::FromRenderFrameHost(destination), - GetSourceURL(destination)); + GetUrlFromRenderFrameHost(destination)); } - router->ReportPasteFromGemini(GetSourceURL(destination), email, verdict, - content_size, bypassed); + router->ReportPasteFromGemini(GetUrlFromRenderFrameHost(destination), email, + verdict, content_size, bypassed); #endif // BUILDFLAG(SAFE_BROWSING_AVAILABLE) } @@ -876,7 +872,7 @@ } content::RenderFrameHost* rfh = web_contents->GetPrimaryMainFrame(); - auto url = GetSourceURL(rfh); + auto url = GetUrlFromRenderFrameHost(rfh); if (!url.is_valid()) { return std::nullopt; } @@ -907,7 +903,7 @@ // inside a cross-origin iframe. if (profile && enterprise_connectors::ContentAnalysisDelegate::IsEnabled( - profile, GetSourceURL(destination), &dialog_data, + profile, GetUrlFromRenderFrameHost(destination), &dialog_data, enterprise_connectors::AnalysisConnector::BULK_DATA_ENTRY)) { dialog_data.text.push_back(std::move(data)); dialog_data.reason = @@ -1456,7 +1452,7 @@ } ui::DataTransferEndpoint dte( - GetSourceURL(rfh), + GetUrlFromRenderFrameHost(rfh), {.off_the_record = rfh->GetBrowserContext()->IsOffTheRecord()}); content::ClipboardEndpoint clipboard_endpoint = content::ClipboardEndpoint::ForFrame( @@ -1511,7 +1507,7 @@ if (rules_service) { base::ElapsedTimer timer; auto verdict = rules_service->GetPasteFromGeminiInChromeVerdict( - GetSourceURL(destination)); + GetUrlFromRenderFrameHost(destination)); base::UmaHistogramTimes( "Enterprise.DataControls.GlicPaste.EvaluationLatency", timer.Elapsed()); @@ -1586,20 +1582,39 @@ std::move(callback)); } +GURL GetUrlFromRenderFrameHost(content::RenderFrameHost* rfh) { + if (!rfh) { + return GURL(); + } + auto* main_frame = rfh->GetMainFrame(); + auto url = main_frame->GetLastCommittedURL(); + if (!url.is_valid() || url.IsAboutBlank() || url.IsAboutSrcdoc()) { + auto origin_url = main_frame->GetLastCommittedOrigin() + .GetTupleOrPrecursorTupleIfOpaque() + .GetURL(); + if (origin_url.is_valid()) { + url = std::move(origin_url); + } else if (!url.is_valid()) { + url = GURL(url::kAboutBlankURL); + } + } + return GetOriginalUrl(url); +} + std::optional<GURL> MaybeOverrideSourceURLForClipboardAccess( content::RenderFrameHost* render_frame_host, const GURL& original_url) { DCHECK(render_frame_host); #if BUILDFLAG(ENABLE_PRINT_PREVIEW) if (printing::PrintPreviewDialogController::IsPrintPreviewURL(original_url)) { - return printing::PrintPreviewDialogController::GetInstance() - ->GetInitiator( - content::WebContents::FromRenderFrameHost(render_frame_host)) - ->GetPrimaryMainFrame() - ->GetLastCommittedURL(); + return GetUrlFromRenderFrameHost( + printing::PrintPreviewDialogController::GetInstance() + ->GetInitiator( + content::WebContents::FromRenderFrameHost(render_frame_host)) + ->GetPrimaryMainFrame()); } #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) - return std::nullopt; + return GetUrlFromRenderFrameHost(render_frame_host); } } // namespace enterprise_data_protection diff --git a/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils.h b/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils.h index 79e734c..af037e9f6 100644 --- a/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils.h +++ b/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils.h @@ -208,8 +208,15 @@ void CopyTextToClipboard(content::RenderFrameHost* rfh, const std::u16string& text); -// Returns the initiator main frame's last committed URL if the `original_url` -// is a Print Preview URL. Returns std::nullopt otherwise. +// Returns the URL to use for data protection checks for `rfh`. If the main +// frame's last committed URL is invalid, about:blank, or about:srcdoc, this +// falls back to the main frame's precursor/tuple origin URL (or about:blank if +// no valid origin tuple exists), and unwraps distilled page URLs. +GURL GetUrlFromRenderFrameHost(content::RenderFrameHost* rfh); + +// Returns the desired URL for clipboard source/destination reporting for +// `render_frame_host`, including resolving the initiator URL when +// `original_url` is a Print Preview URL. std::optional<GURL> MaybeOverrideSourceURLForClipboardAccess( content::RenderFrameHost* render_frame_host, const GURL& original_url); diff --git a/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils_types.cc b/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils_types.cc index 6fa3e62..44b40f2 100644 --- a/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils_types.cc +++ b/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils_types.cc @@ -5,6 +5,7 @@ #include "chrome/browser/enterprise/data_protection/data_protection_clipboard_utils_types.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/enterprise/data_protection/data_protection_clipboard_utils.h" #include "chrome/browser/glic/host/guest_util.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/clipboard_types.h" @@ -87,6 +88,15 @@ const content::ClipboardEndpoint& source) { BasicPasteSource cached; cached.data_transfer_endpoint = source.data_transfer_endpoint(); + if (!cached.data_transfer_endpoint && source.render_frame_host()) { + cached.data_transfer_endpoint = ui::DataTransferEndpoint( + GetUrlFromRenderFrameHost(source.render_frame_host()), + { + .off_the_record = source.render_frame_host() + ->GetBrowserContext() + ->IsOffTheRecord(), + }); + } if (source.browser_context()) { cached.browser_context = source.browser_context()->GetWeakPtr(); } diff --git a/chrome/browser/enterprise/data_protection/data_protection_navigation_observer.cc b/chrome/browser/enterprise/data_protection/data_protection_navigation_observer.cc index 32fe9a344..f36d5f2f 100644 --- a/chrome/browser/enterprise/data_protection/data_protection_navigation_observer.cc +++ b/chrome/browser/enterprise/data_protection/data_protection_navigation_observer.cc @@ -15,14 +15,14 @@ #include "base/time/time.h" #include "chrome/browser/enterprise/connectors/connectors_service.h" #include "chrome/browser/enterprise/data_controls/chrome_rules_service.h" +#include "chrome/browser/enterprise/data_protection/data_protection_clipboard_utils.h" #include "chrome/browser/enterprise/data_protection/data_protection_features.h" #include "chrome/browser/enterprise/data_protection/data_protection_url_lookup_service_factory.h" +#include "chrome/browser/enterprise/data_protection/data_protection_utils.h" #include "chrome/browser/interstitials/enterprise_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/url_constants.h" #include "chrome/common/webui_url_constants.h" -#include "components/dom_distiller/core/url_constants.h" -#include "components/dom_distiller/core/url_utils.h" #include "components/enterprise/data_protection/data_protection_url_lookup_service.h" #include "components/enterprise/data_protection/utils.h" #include "components/safe_browsing/buildflags.h" @@ -98,17 +98,6 @@ } #endif // BUILDFLAG(SAFE_BROWSING_AVAILABLE) -GURL GetOriginalUrl(const GURL& url) { - if (GURL got_url = - dom_distiller::url_utils::GetOriginalUrlFromDistillerUrl(url); - got_url.is_valid()) { - return got_url; - } else { - VLOG(1) << __func__ << " got a invalid url: " << got_url; - } - return url; -} - void RunPendingNavigationCallback( content::WebContents* web_contents, DataProtectionNavigationObserver::Callback callback) { @@ -313,14 +302,15 @@ return; } - if (!web_contents->GetLastCommittedURL().is_valid()) { + const GURL original_url = + GetUrlFromRenderFrameHost(web_contents->GetPrimaryMainFrame()); + if (!original_url.is_valid()) { std::move(callback).Run(UrlSettings::None()); return; } std::string identifier = GetIdentifier(profile); - const GURL original_url = GetOriginalUrl(web_contents->GetLastCommittedURL()); DataProtectionPageUserData::UpdateDataControlsScreenshotState( GetPageFromWebContents(web_contents), identifier, IsScreenshotAllowedByDataControls(profile, original_url)); diff --git a/chrome/browser/enterprise/data_protection/data_protection_utils.cc b/chrome/browser/enterprise/data_protection/data_protection_utils.cc new file mode 100644 index 0000000..93490f1 --- /dev/null +++ b/chrome/browser/enterprise/data_protection/data_protection_utils.cc @@ -0,0 +1,24 @@ +// Copyright 2026 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/enterprise/data_protection/data_protection_utils.h" + +#include "base/logging.h" +#include "components/dom_distiller/core/url_utils.h" +#include "url/gurl.h" + +namespace enterprise_data_protection { + +GURL GetOriginalUrl(const GURL& url) { + if (GURL original_url = + dom_distiller::url_utils::GetOriginalUrlFromDistillerUrl(url); + original_url.is_valid()) { + return original_url; + } else { + VLOG(1) << __func__ << " got a invalid url: " << original_url; + } + return url; +} + +} // namespace enterprise_data_protection diff --git a/chrome/browser/enterprise/data_protection/data_protection_utils.h b/chrome/browser/enterprise/data_protection/data_protection_utils.h new file mode 100644 index 0000000..cd9a6fc --- /dev/null +++ b/chrome/browser/enterprise/data_protection/data_protection_utils.h @@ -0,0 +1,20 @@ +// Copyright 2026 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ENTERPRISE_DATA_PROTECTION_DATA_PROTECTION_UTILS_H_ +#define CHROME_BROWSER_ENTERPRISE_DATA_PROTECTION_DATA_PROTECTION_UTILS_H_ + +#include "url/gurl.h" + +namespace enterprise_data_protection { + +// Returns the URL that data protection checks should apply to for `url`. If +// `url` is a distilled page URL (chrome-distiller://), the original URL of the +// distilled page is returned so that policies apply to the page the content +// actually comes from. `url` is returned as-is otherwise. +GURL GetOriginalUrl(const GURL& url); + +} // namespace enterprise_data_protection + +#endif // CHROME_BROWSER_ENTERPRISE_DATA_PROTECTION_DATA_PROTECTION_UTILS_H_ diff --git a/chrome/browser/enterprise/data_protection/print_utils.cc b/chrome/browser/enterprise/data_protection/print_utils.cc index cb424c0d6..e578ada 100644 --- a/chrome/browser/enterprise/data_protection/print_utils.cc +++ b/chrome/browser/enterprise/data_protection/print_utils.cc @@ -11,6 +11,7 @@ #include "base/containers/span.h" #include "base/feature_list.h" #include "base/memory/read_only_shared_memory_region.h" +#include "chrome/browser/enterprise/data_protection/data_protection_clipboard_utils.h" #include "chrome/browser/profiles/profile.h" #include "components/device_event_log/device_event_log.h" #include "components/enterprise/buildflags/buildflags.h" @@ -149,7 +150,8 @@ bool enabled = enterprise_connectors::ContentAnalysisDelegate::IsEnabled( Profile::FromBrowserContext(web_contents->GetBrowserContext()), - web_contents->GetOutermostWebContents()->GetLastCommittedURL(), + GetUrlFromRenderFrameHost( + web_contents->GetOutermostWebContents()->GetPrimaryMainFrame()), &scanning_data, enterprise_connectors::AnalysisConnector::PRINT); if (enabled && ShouldScan(context)) { diff --git a/content/public/browser/clipboard_types.cc b/content/public/browser/clipboard_types.cc index daa934c..6a0aa70 100644 --- a/content/public/browser/clipboard_types.cc +++ b/content/public/browser/clipboard_types.cc @@ -237,10 +237,6 @@ RenderFrameHost& rfh) { auto* render_frame_host_main_frame = rfh.GetMainFrame(); auto source_url = render_frame_host_main_frame->GetLastCommittedURL(); - if (!source_url.is_valid()) { - return std::nullopt; - } - if (auto maybe_url = GetContentClient() ->browser() ->MaybeOverrideSourceURLForClipboardAccess( @@ -248,6 +244,10 @@ source_url = *maybe_url; } + if (!source_url.is_valid()) { + return std::nullopt; + } + return ui::DataTransferEndpoint( source_url, ui::DataTransferEndpointOptions{ diff --git a/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils_unittest.cc b/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils_unittest.cc ... (file diff truncated)
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils_unittest.cc b/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils_unittest.cc
index 9869109..21eb6e5 100644
--- a/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils_unittest.cc
+++ b/chrome/browser/enterprise/data_protection/data_protection_clipboard_utils_unittest.cc
@@ -28,6 +28,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/common/drop_data.h"
#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -1550,4 +1551,116 @@
EXPECT_FALSE(PrepopulateFindBarTextAllowed(source, destination_blocked));
}
+class DataProtectionClipboardInitialEmptyDocumentPopupTest
+ : public DataProtectionClipboardTest {
+ public:
+ void SetUp() override {
+ DataProtectionClipboardTest::SetUp();
+ scoped_features_.InitWithFeatures(
+ {data_controls::kDataControlsSearchWith,
+ enterprise_connectors::kContentAnalysisClipboardCopy},
+ {});
+ opener_web_contents_ =
+ content::WebContentsTester::CreateTestWebContents(profile_, nullptr);
+ content::WebContentsTester::For(opener_web_contents_.get())
+ ->NavigateAndCommit(GURL("https://source.com/page.html"));
+
+ popup_web_contents_ = content::WebContentsTester::CreateTestWebContents(
+ profile_, opener_web_contents_->GetSiteInstance());
+ auto simulator = content::NavigationSimulator::CreateRendererInitiated(
+ GURL(url::kAboutBlankURL), popup_web_contents_->GetPrimaryMainFrame());
+ simulator->SetInitiatorFrame(opener_web_contents_->GetPrimaryMainFrame());
+ simulator->Commit();
+
+ ASSERT_TRUE(popup_web_contents_->GetLastCommittedURL().IsAboutBlank());
+ ASSERT_EQ(
+ popup_web_contents_->GetPrimaryMainFrame()->GetLastCommittedOrigin(),
+ url::Origin::Create(GURL("https://source.com")));
+ }
+
+ void SetBlockCopyingFromSourceURLRule() {
+ data_controls::SetDataControls(profile_->GetPrefs(), {R"({
+ "sources": {
+ "urls": ["source.com"]
+ },
+ "restrictions": [
+ {"class": "CLIPBOARD", "level": "BLOCK"}
+ ]
+ })"});
+ }
+
+ void SetBlockCopyingFromWildcardURLRule() {
+ data_controls::SetDataControls(profile_->GetPrefs(), {R"({
+ "sources": {
+ "urls": ["*"]
+ },
+ "restrictions": [
+ {"class": "CLIPBOARD", "level": "BLOCK"}
+ ]
+ })"});
+ }
+
+ protected:
+ content::RenderViewHostTestEnabler test_render_host_factories_;
+ std::unique_ptr<content::WebContents> opener_web_contents_;
+ std::unique_ptr<content::WebContents> popup_web_contents_;
+};
+
+TEST_F(DataProtectionClipboardInitialEmptyDocumentPopupTest,
+ CopyBlockedBySourceURLRule) {
+ SetBlockCopyingFromSourceURLRule();
+
+ auto endpoint = content::CreateClipboardEndpoint(
+ *popup_web_contents_->GetPrimaryMainFrame());
+ ASSERT_TRUE(endpoint.data_transfer_endpoint());
+ ASSERT_TRUE(endpoint.data_transfer_endpoint()->GetURL());
+ EXPECT_EQ(*endpoint.data_transfer_endpoint()->GetURL(),
+ GURL("https://source.com/"));
+
+ base::test::TestFuture<const ui::ClipboardFormatType&,
+ const content::ClipboardPasteData&,
+ std::optional<std::u16string>>
+ future;
+ IsClipboardCopyAllowedByPolicy(endpoint, CopyMetadata(),
+ MakeClipboardPasteData("confidential", "", {}),
+ future.GetCallback());
+ auto data = future.Get<1>();
+ EXPECT_TRUE(data.empty());
+ EXPECT_FALSE(IsClipboardCopyAllowedByPolicyForUI(popup_web_contents_.get()));
+ EXPECT_FALSE(IsSearchWithAllowed(popup_web_contents_.get()));
+ EXPECT_FALSE(CanPopulateFindBarFromSelection(popup_web_contents_.get()));
+}
+
+TEST_F(DataProtectionClipboardInitialEmptyDocumentPopupTest,
+ CopyBlockedByWildcardURLRuleOnUncommittedTabWithoutOpener) {
+ SetBlockCopyingFromWildcardURLRule();
+
+ std::unique_ptr<content::WebContents> uncommitted_web_contents =
+ content::WebContentsTester::CreateTestWebContents(profile_, nullptr);
+ ASSERT_TRUE(uncommitted_web_contents->GetLastCommittedURL().is_empty());
+ ASSERT_TRUE(uncommitted_web_contents->GetPrimaryMainFrame()
+ ->GetLastCommittedOrigin()
+ .opaque());
+
+ auto endpoint = content::CreateClipboardEndpoint(
+ *uncommitted_web_contents->GetPrimaryMainFrame());
+ ASSERT_TRUE(endpoint.data_transfer_endpoint());
+ ASSERT_TRUE(endpoint.data_transfer_endpoint()->GetURL());
+ EXPECT_EQ(*endpoint.data_transfer_endpoint()->GetURL(),
+ GURL(url::kAboutBlankURL));
+
+ base::test::TestFuture<const ui::ClipboardFormatType&,
+ const content::ClipboardPasteData&,
+ std::optional<std::u16string>>
+ future;
+ IsClipboardCopyAllowedByPolicy(endpoint, CopyMetadata(),
+ MakeClipboardPasteData("confidential", "", {}),
+ future.GetCallback());
+ auto data = future.Get<1>();
+ EXPECT_TRUE(data.empty());
+ EXPECT_FALSE(
+ IsClipboardCopyAllowedByPolicyForUI(uncommitted_web_contents.get()));
+ EXPECT_FALSE(IsSearchWithAllowed(uncommitted_web_contents.get()));
+}
+
} // namespace enterprise_data_protection
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page