Chrome · Global Media Controls
CVE-2026-17983
Logic Error in Global Media Controls
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifchrome/browser/ui/global_media_controls/presentation_request_notification_item.cc |
modified |
Files Changed
chrome/browser/ui/global_media_controls/presentation_request_notification_item.ccchrome/browser/ui/global_media_controls/presentation_request_notification_item.hchrome/browser/ui/global_media_controls/presentation_request_notification_item_unittest.cc
Patch
From a019509362c68d8ab8669fe28013822301cb73a5 Mon Sep 17 00:00:00 2001
From: Muyao Xu <muyaoxu@google.com>
Date: Wed, 10 Jun 2026 16:07:33 -0700
Subject: [PATCH] [MediaRouter] Only use Mediasession metadata for same-origin requests
Onl use the tab's MediaSession metadata for the
PresentationRequestNotificationItem when they are from the same
origin.
Bug: 519744561
Change-Id: Ia95f35f2226597e6f81bfe825be53f67ac78d6f9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7916088
Reviewed-by: Jordan Bayles <jophba@chromium.org>
Commit-Queue: Muyao Xu <muyaoxu@google.com>
Cr-Commit-Position: refs/heads/main@{#1644954}
---
diff --git a/chrome/browser/ui/global_media_controls/presentation_request_notification_item.cc b/chrome/browser/ui/global_media_controls/presentation_request_notification_item.cc
index d88b9ed..79aa20f0 100644
--- a/chrome/browser/ui/global_media_controls/presentation_request_notification_item.cc
+++ b/chrome/browser/ui/global_media_controls/presentation_request_notification_item.cc
@@ -11,6 +11,7 @@
#include "components/global_media_controls/public/media_item_manager.h"
#include "components/media_message_center/media_notification_util.h"
#include "content/public/browser/media_session.h"
+#include "content/public/browser/render_frame_host.h"
#include "services/media_session/public/cpp/media_image_manager.h"
#include "services/media_session/public/cpp/media_metadata.h"
#include "ui/gfx/image/image_skia.h"
@@ -155,9 +156,10 @@
if (!provider_->is_bound()) {
return;
}
- // If we have metadata from the media session, use that.
- media_session::MediaMetadata data =
- metadata_.value_or(media_session::MediaMetadata{});
+ media_session::MediaMetadata data;
+ if (metadata_.has_value() && ShouldShowMediaSessionMetadata()) {
+ data = *metadata_;
+ }
if (media_message_center::IsOriginGoodForDisplay(request_.frame_origin)) {
// `request_` has more accurate origin info than `metadata_` e.g. when the
@@ -179,12 +181,17 @@
if (!provider_->is_bound()) {
return;
}
- (*provider_)->OnArtworkImageChanged(artwork_image_);
- if (!favicon_image_.isNull()) {
+
+ const bool should_show_metadata = ShouldShowMediaSessionMetadata();
+ (*provider_)
+ ->OnArtworkImageChanged(should_show_metadata ? artwork_image_
+ : gfx::ImageSkia());
+
+ if (should_show_metadata && !favicon_image_.isNull()) {
(*provider_)->OnFaviconImageChanged(favicon_image_);
return;
}
- // Otherwise, get one ourselves.
+
auto* web_contents = GetWebContentsFromPresentationRequest(request_);
if (web_contents) {
favicon::FaviconDriver* favicon_driver =
@@ -209,3 +216,21 @@
favicon_image_ = GetCorrectColorTypeImage(bitmap).value_or(gfx::ImageSkia());
UpdatePickerWithImages();
}
+
+bool PresentationRequestNotificationItem::ShouldShowMediaSessionMetadata()
+ const {
+ auto* web_contents = GetWebContentsFromPresentationRequest(request_);
+ if (!web_contents) {
+ return false;
+ }
+ auto* media_session = GetMediaSession(web_contents);
+ if (!media_session) {
+ return false;
+ }
+ content::RenderFrameHost* routed_frame = media_session->GetRoutedFrame();
+ if (!routed_frame) {
+ return true;
+ }
+ return routed_frame->GetLastCommittedOrigin().IsSameOriginWith(
+ request_.frame_origin);
+}
diff --git a/chrome/browser/ui/global_media_controls/presentation_request_notification_item.h b/chrome/browser/ui/global_media_controls/presentation_request_notification_item.h
index e32f83a2..7210879 100644
--- a/chrome/browser/ui/global_media_controls/presentation_request_notification_item.h
+++ b/chrome/browser/ui/global_media_controls/presentation_request_notification_item.h
@@ -86,6 +86,10 @@
void OnArtworkBitmap(const SkBitmap& bitmap);
void OnFaviconBitmap(const SkBitmap& bitmap);
+ // Returns true if the origin of the active MediaSession's routed frame is the
+ // same as the origin of the frame that initiated the presentation request.
+ bool ShouldShowMediaSessionMetadata() const;
+
// True if the item is created from a default PresentationRequest, which means
// |context_| is set to nullptr in the constructor.
const bool is_default_presentation_request_;
diff --git a/chrome/browser/ui/global_media_controls/presentation_request_notification_item_unittest.cc b/chrome/browser/ui/global_media_controls/presentation_request_notification_item_unittest.cc
index 8d532a2..027e83d 100644
--- a/chrome/browser/ui/global_media_controls/presentation_request_notification_item_unittest.cc
+++ b/chrome/browser/ui/global_media_controls/presentation_request_notification_item_unittest.cc
@@ -8,7 +8,10 @@
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "components/global_media_controls/public/test/mock_device_service.h"
#include "components/media_router/common/mojom/media_router.mojom.h"
+#include "content/public/browser/web_contents.h"
#include "content/public/test/mock_media_session.h"
+#include "content/public/test/navigation_simulator.h"
+#include "content/public/test/test_renderer_host.h"
#include "services/media_session/public/cpp/media_image.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -21,6 +24,7 @@
protected:
void SetUp() override {
ChromeRenderViewHostTestHarness::SetUp();
+ NavigateAndCommit(GURL("https://example.com"));
PresentationRequestNotificationItem::SetMediaSessionForTest(
&media_session_);
@@ -79,3 +83,70 @@
item_->MediaSessionImagesChanged(
{{media_session::mojom::MediaSessionImageType::kArtwork, {image}}});
}
+
+TEST_F(PresentationRequestNotificationItemTest,
+ MediaSessionMetadataChanged_RoutedFrameOriginMatch) {
+ EXPECT_CALL(media_session_, GetRoutedFrame())
+ .WillRepeatedly(testing::Return(main_rfh()));
+
+ media_session::MediaMetadata metadata;
+ metadata.source_title = u"some-other-domain.com";
+ metadata.artist = u"My title";
+
+ EXPECT_CALL(*provider_, OnMetadataChanged)
+ .WillOnce([metadata](const media_session::MediaMetadata& metadata_arg) {
+ EXPECT_EQ(u"example.com", metadata_arg.source_title);
+ EXPECT_EQ(metadata.artist, metadata_arg.artist);
+ });
+ item_->MediaSessionMetadataChanged(metadata);
+}
+
+TEST_F(PresentationRequestNotificationItemTest,
+ MediaSessionMetadataChanged_RoutedFrameOriginMismatch) {
+ content::RenderFrameHost* child_rfh =
+ content::RenderFrameHostTester::For(main_rfh())
+ ->AppendChild("child_frame");
+ child_rfh = content::NavigationSimulator::NavigateAndCommitFromDocument(
+ GURL("https://other.com"), child_rfh);
+
+ EXPECT_CALL(media_session_, GetRoutedFrame())
+ .WillRepeatedly(testing::Return(child_rfh));
+
+ media_session::MediaMetadata metadata;
+ metadata.source_title = u"some-other-domain.com";
+ metadata.artist = u"My title";
+
+ EXPECT_CALL(*provider_, OnMetadataChanged)
+ .WillOnce([this](const media_session::MediaMetadata& metadata_arg) {
+ EXPECT_EQ(u"example.com", metadata_arg.source_title);
+ EXPECT_TRUE(metadata_arg.title.empty());
+ EXPECT_EQ(web_contents()->GetTitle(), metadata_arg.artist);
+ });
+ item_->MediaSessionMetadataChanged(metadata);
+}
+
+TEST_F(PresentationRequestNotificationItemTest,
+ MediaSessionImagesChanged_RoutedFrameOriginMismatch) {
+ content::RenderFrameHost* child_rfh =
+ content::RenderFrameHostTester::For(main_rfh())
+ ->AppendChild("child_frame");
+ child_rfh = content::NavigationSimulator::NavigateAndCommitFromDocument(
+ GURL("https://other.com"), child_rfh);
+
+ EXPECT_CALL(media_session_, GetRoutedFrame())
+ .WillRepeatedly(testing::Return(child_rfh));
+
+ media_session::MediaImage image;
+ image.src = GURL{"https://example.com"};
+ image.sizes = {{100, 100}};
+
+ EXPECT_CALL(*provider_, OnArtworkImageChanged)
+ .WillOnce(
+ [](const gfx::ImageSkia& image) { EXPECT_TRUE(image.isNull()); });
+ EXPECT_CALL(*provider_, OnFaviconImageChanged)
+ .WillOnce(
+ [](const gfx::ImageSkia& image) { EXPECT_TRUE(image.isNull()); });
+
+ item_->MediaSessionImagesChanged(
+ {{media_session::mojom::MediaSessionImageType::kArtwork, {image}}});
+}
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/chrome/browser/ui/global_media_controls/presentation_request_notification_item_unittest.cc b/chrome/browser/ui/global_media_controls/presentation_request_notification_item_unittest.cc
index 8d532a2..027e83d 100644
--- a/chrome/browser/ui/global_media_controls/presentation_request_notification_item_unittest.cc
+++ b/chrome/browser/ui/global_media_controls/presentation_request_notification_item_unittest.cc
@@ -8,7 +8,10 @@
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "components/global_media_controls/public/test/mock_device_service.h"
#include "components/media_router/common/mojom/media_router.mojom.h"
+#include "content/public/browser/web_contents.h"
#include "content/public/test/mock_media_session.h"
+#include "content/public/test/navigation_simulator.h"
+#include "content/public/test/test_renderer_host.h"
#include "services/media_session/public/cpp/media_image.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -21,6 +24,7 @@
protected:
void SetUp() override {
ChromeRenderViewHostTestHarness::SetUp();
+ NavigateAndCommit(GURL("https://example.com"));
PresentationRequestNotificationItem::SetMediaSessionForTest(
&media_session_);
@@ -79,3 +83,70 @@
item_->MediaSessionImagesChanged(
{{media_session::mojom::MediaSessionImageType::kArtwork, {image}}});
}
+
+TEST_F(PresentationRequestNotificationItemTest,
+ MediaSessionMetadataChanged_RoutedFrameOriginMatch) {
+ EXPECT_CALL(media_session_, GetRoutedFrame())
+ .WillRepeatedly(testing::Return(main_rfh()));
+
+ media_session::MediaMetadata metadata;
+ metadata.source_title = u"some-other-domain.com";
+ metadata.artist = u"My title";
+
+ EXPECT_CALL(*provider_, OnMetadataChanged)
+ .WillOnce([metadata](const media_session::MediaMetadata& metadata_arg) {
+ EXPECT_EQ(u"example.com", metadata_arg.source_title);
+ EXPECT_EQ(metadata.artist, metadata_arg.artist);
+ });
+ item_->MediaSessionMetadataChanged(metadata);
+}
+
+TEST_F(PresentationRequestNotificationItemTest,
+ MediaSessionMetadataChanged_RoutedFrameOriginMismatch) {
+ content::RenderFrameHost* child_rfh =
+ content::RenderFrameHostTester::For(main_rfh())
+ ->AppendChild("child_frame");
+ child_rfh = content::NavigationSimulator::NavigateAndCommitFromDocument(
+ GURL("https://other.com"), child_rfh);
+
+ EXPECT_CALL(media_session_, GetRoutedFrame())
+ .WillRepeatedly(testing::Return(child_rfh));
+
+ media_session::MediaMetadata metadata;
+ metadata.source_title = u"some-other-domain.com";
+ metadata.artist = u"My title";
+
+ EXPECT_CALL(*provider_, OnMetadataChanged)
+ .WillOnce([this](const media_session::MediaMetadata& metadata_arg) {
+ EXPECT_EQ(u"example.com", metadata_arg.source_title);
+ EXPECT_TRUE(metadata_arg.title.empty());
+ EXPECT_EQ(web_contents()->GetTitle(), metadata_arg.artist);
+ });
+ item_->MediaSessionMetadataChanged(metadata);
+}
+
+TEST_F(PresentationRequestNotificationItemTest,
+ MediaSessionImagesChanged_RoutedFrameOriginMismatch) {
+ content::RenderFrameHost* child_rfh =
+ content::RenderFrameHostTester::For(main_rfh())
+ ->AppendChild("child_frame");
+ child_rfh = content::NavigationSimulator::NavigateAndCommitFromDocument(
+ GURL("https://other.com"), child_rfh);
+
+ EXPECT_CALL(media_session_, GetRoutedFrame())
+ .WillRepeatedly(testing::Return(child_rfh));
+
+ media_session::MediaImage image;
+ image.src = GURL{"https://example.com"};
+ image.sizes = {{100, 100}};
+
+ EXPECT_CALL(*provider_, OnArtworkImageChanged)
+ .WillOnce(
+ [](const gfx::ImageSkia& image) { EXPECT_TRUE(image.isNull()); });
+ EXPECT_CALL(*provider_, OnFaviconImageChanged)
+ .WillOnce(
+ [](const gfx::ImageSkia& image) { EXPECT_TRUE(image.isNull()); });
+
+ item_->MediaSessionImagesChanged(
+ {{media_session::mojom::MediaSessionImageType::kArtwork, {image}}});
+}
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