Low chrome UAF 🔧 Commit mapped

Overview

Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in Media
DescriptionUse after free in Media
ComponentMedia
Bug ClassUAF
Tracker559776445
Fix commit83523e3cf61d (chromium/src) +52/-1
CISA KEVNot listed
CreditedGoogle
Disclosed2026-10-20

Changed Functions

FunctionChangeNotes
TEST_F
chrome/browser/media/android/cdm/media_drm_storage_factory_unittest.cc
modified
if
chrome/browser/media/BUILD.gn
modified

Files Changed

  • chrome/browser/media/BUILD.gn
  • chrome/browser/media/android/cdm/media_drm_storage_factory.cc
  • chrome/browser/media/android/cdm/media_drm_storage_factory_unittest.cc
From 83523e3cf61d7b11285a38b4fabbd70e4019a101 Mon Sep 17 00:00:00 2001
From: Vikram Pasupathy <[email protected]>
Date: Mon, 21 Sep 2026 16:25:59 -0700
Subject: [PATCH] Disallow MediaDrmStorage creation for off-the-record profiles

On Android, persistent MediaDrm state is withheld in Incognito via
renderer-side key-system filtering, but CreateMediaDrmStorage() did not
verify whether the requesting RenderFrameHost belongs to an
off-the-record profile.

Because media.media_drm_storage is not in the Incognito pref allowlist,
binding MediaDrmStorageImpl against an OTR PrefService allowed pref
reads to fall through to the regular profile's store.

Gate CreateMediaDrmStorage() on !profile->IsOffTheRecord() so the
receiver is dropped and CDM creation fails closed in Incognito.

This will not affect behavior, as incognito on Android Chrome already
does not allow playback. Code reference here:
https://source.chromium.org/chromium/chromium/src/+/main:components/cdm/renderer/key_system_support_update.cc;l=307-313

Bug: 559776445
Change-Id: I7385cd2d74b4f870607c318e09ef1931641dc449
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8421816
Commit-Queue: Vikram Pasupathy <[email protected]>
Reviewed-by: Frank Liberato <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1702184}
---
diff --git a/chrome/browser/media/android/cdm/media_drm_storage_factory.cc b/chrome/browser/media/android/cdm/media_drm_storage_factory.cc
index ab42a8d..c3e5411 100644
--- a/chrome/browser/media/android/cdm/media_drm_storage_factory.cc
+++ b/chrome/browser/media/android/cdm/media_drm_storage_factory.cc
@@ -108,6 +108,10 @@
 
   Profile* profile = Profile::FromBrowserContext(browser_context);
   DCHECK(profile) << "Profile not available.";
+  if (profile->IsOffTheRecord()) {
+    DVLOG(1) << __func__ << ": MediaDrm storage not available off the record.";
+    return;
+  }
 
   PrefService* pref_service = profile->GetPrefs();
   DCHECK(pref_service) << "PrefService not available.";
diff --git a/chrome/browser/media/android/cdm/media_drm_storage_factory_unittest.cc b/chrome/browser/media/android/cdm/media_drm_storage_factory_unittest.cc
new file mode 100644
index 0000000..1c8875a
--- /dev/null
+++ b/chrome/browser/media/android/cdm/media_drm_storage_factory_unittest.cc
@@ -0,0 +1,42 @@
+// 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/media/android/cdm/media_drm_storage_factory.h"
+
+#include <memory>
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/navigation_simulator.h"
+#include "content/public/test/web_contents_tester.h"
+#include "media/mojo/mojom/media_drm_storage.mojom.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+using MediaDrmStorageFactoryTest = ChromeRenderViewHostTestHarness;
+
+TEST_F(MediaDrmStorageFactoryTest, RejectsOffTheRecordProfile) {
+  const GURL kTestOrigin("https://example.com");
+  content::NavigationSimulator::NavigateAndCommitFromBrowser(web_contents(),
+                                                             kTestOrigin);
+  mojo::Remote<media::mojom::MediaDrmStorage> regular_storage;
+  CreateMediaDrmStorage(main_rfh(),
+                        regular_storage.BindNewPipeAndPassReceiver());
+  regular_storage.FlushForTesting();
+  EXPECT_TRUE(regular_storage.is_connected());
+
+  Profile* otr_profile =
+      profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true);
+  std::unique_ptr<content::WebContents> otr_web_contents =
+      content::WebContentsTester::CreateTestWebContents(otr_profile, nullptr);
+  content::NavigationSimulator::NavigateAndCommitFromBrowser(
+      otr_web_contents.get(), kTestOrigin);
+  mojo::Remote<media::mojom::MediaDrmStorage> otr_storage;
+  CreateMediaDrmStorage(otr_web_contents->GetPrimaryMainFrame(),
+                        otr_storage.BindNewPipeAndPassReceiver());
+  otr_storage.FlushForTesting();
+  EXPECT_FALSE(otr_storage.is_connected());
+}
diff --git a/chrome/browser/media/BUILD.gn b/chrome/browser/media/BUILD.gn
index 1390d0cb..5f98a5e 100644
--- a/chrome/browser/media/BUILD.gn
+++ b/chrome/browser/media/BUILD.gn
@@ -148,13 +148,18 @@
   }
 
   if (is_android) {
-    sources += [ "android/cdm/media_drm_origin_id_manager_unittest.cc" ]
+    sources += [
+      "android/cdm/media_drm_origin_id_manager_unittest.cc",
+      "android/cdm/media_drm_storage_factory_unittest.cc",
+    ]
     deps += [
       ":impl",
       "//base/test:test_support",
       "//chrome/test:test_support",
       "//components/prefs:test_support",
       "//content/test:test_support",
+      "//media/mojo/mojom",
+      "//mojo/public/cpp/bindings",
     ]
   }
 
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/chrome/browser/media/android/cdm/media_drm_storage_factory_unittest.cc b/chrome/browser/media/android/cdm/media_drm_storage_factory_unittest.cc
new file mode 100644
index 0000000..1c8875a
--- /dev/null
+++ b/chrome/browser/media/android/cdm/media_drm_storage_factory_unittest.cc
@@ -0,0 +1,42 @@
+// 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/media/android/cdm/media_drm_storage_factory.h"
+
+#include <memory>
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/navigation_simulator.h"
+#include "content/public/test/web_contents_tester.h"
+#include "media/mojo/mojom/media_drm_storage.mojom.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+using MediaDrmStorageFactoryTest = ChromeRenderViewHostTestHarness;
+
+TEST_F(MediaDrmStorageFactoryTest, RejectsOffTheRecordProfile) {
+  const GURL kTestOrigin("https://example.com");
+  content::NavigationSimulator::NavigateAndCommitFromBrowser(web_contents(),
+                                                             kTestOrigin);
+  mojo::Remote<media::mojom::MediaDrmStorage> regular_storage;
+  CreateMediaDrmStorage(main_rfh(),
+                        regular_storage.BindNewPipeAndPassReceiver());
+  regular_storage.FlushForTesting();
+  EXPECT_TRUE(regular_storage.is_connected());
+
+  Profile* otr_profile =
+      profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true);
+  std::unique_ptr<content::WebContents> otr_web_contents =
+      content::WebContentsTester::CreateTestWebContents(otr_profile, nullptr);
+  content::NavigationSimulator::NavigateAndCommitFromBrowser(
+      otr_web_contents.get(), kTestOrigin);
+  mojo::Remote<media::mojom::MediaDrmStorage> otr_storage;
+  CreateMediaDrmStorage(otr_web_contents->GetPrimaryMainFrame(),
+                        otr_storage.BindNewPipeAndPassReceiver());
+  otr_storage.FlushForTesting();
+  EXPECT_FALSE(otr_storage.is_connected());
+}
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.