Low chrome UAF 🔧 Commit mapped

Overview

Low
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in DevTools
DescriptionUse after free in DevTools
ComponentDevTools
Bug ClassUAF
Tracker523442920
Fix commit23294e43bec4 (v8/v8) +38/-4
CISA KEVNot listed
CreditedGoogle
Disclosed2026-09-08

Changed Functions

FunctionChangeNotes
get
test/inspector/runtime/regress-523442920.js
modified

Files Changed

  • src/inspector/v8-console.cc
  • test/inspector/runtime/regress-523442920-expected.txt
  • test/inspector/runtime/regress-523442920.js
From 23294e43bec49915a9f3fb9f3b45acc559d1bd6e Mon Sep 17 00:00:00 2001
From: Yang Guo <[email protected]>
Date: Mon, 10 Aug 2026 05:11:17 +0000
Subject: [PATCH] [inspector] Pin InspectedContext in ConsoleHelper to prevent UAF

ConsoleHelper::injectedScript() previously dropped its local
shared_ptr<InspectedContext> before returning the raw InjectedScript*
pointer. If the CommandLineAPI inspect function was captured and invoked
from a page script outside an active ContextScope, synchronous context
destruction during object serialization caused a use-after-free in
InjectedScript::wrapObjectMirror.

Keep a std::shared_ptr<InspectedContext> in ConsoleHelper so the
context remains pinned during inspectImpl execution.

TAG=agy
CONV=812b1007-2667-4bf3-8c0b-7669dff6da64

Fixed: 523442920
Change-Id: I96dcd0c3c04b02d3ab3a92a0a3dbb6a0876b25e8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/8225404
Commit-Queue: Simon Zünd <[email protected]>
Auto-Submit: Yang Guo <[email protected]>
Reviewed-by: Simon Zünd <[email protected]>
Cr-Commit-Position: refs/heads/main@{#109151}
---

diff --git a/src/inspector/v8-console.cc b/src/inspector/v8-console.cc
index 0fa7caf..0ad21a5 100644
--- a/src/inspector/v8-console.cc
+++ b/src/inspector/v8-console.cc
@@ -67,10 +67,9 @@
   int groupId() const { return m_inspector->contextGroupId(contextId()); }
 
   InjectedScript* injectedScript(int sessionId) {
-    std::shared_ptr<InspectedContext> context =
-        m_inspector->getContext(groupId(), contextId());
-    if (!context) return nullptr;
-    return context->getInjectedScript(sessionId);
+    m_inspectedContext = m_inspector->getContext(groupId(), contextId());
+    if (!m_inspectedContext) return nullptr;
+    return m_inspectedContext->getInjectedScript(sessionId);
   }
 
   V8InspectorSessionImpl* session(int sessionId) {
@@ -210,6 +209,7 @@
   const v8::debug::ConsoleCallArguments& m_info;
   const v8::debug::ConsoleContext& m_consoleContext;
   V8InspectorImpl* m_inspector;
+  std::shared_ptr<InspectedContext> m_inspectedContext;
 };
 
 void createBoundFunctionProperty(
diff --git a/test/inspector/runtime/regress-523442920-expected.txt b/test/inspector/runtime/regress-523442920-expected.txt
new file mode 100644
index 0000000..ac306d2
--- /dev/null
+++ b/test/inspector/runtime/regress-523442920-expected.txt
@@ -0,0 +1,2 @@
+Tests that destroying context during inspect does not cause UAF (regress-523442920).
+Success (no crash).
diff --git a/test/inspector/runtime/regress-523442920.js b/test/inspector/runtime/regress-523442920.js
new file mode 100644
index 0000000..d3442cd
--- /dev/null
+++ b/test/inspector/runtime/regress-523442920.js
@@ -0,0 +1,32 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+let {session, contextGroup, Protocol} =
+  InspectorTest.start('Tests that destroying context during inspect does not cause UAF (regress-523442920).');
+
+(async function test() {
+  await Protocol.Runtime.enable();
+
+  // Capture CommandLineAPI inspect function.
+  await Protocol.Runtime.evaluate({
+    expression: 'globalThis.savedInspect = inspect;',
+    includeCommandLineAPI: true,
+  });
+
+  // Call savedInspect from page-level execution where no ContextScope is active.
+  contextGroup.addScript(`
+    let e = new Error();
+    delete e.name;
+    Object.defineProperty(Object.getPrototypeOf(e), 'name', {
+      get() {
+        inspector.fireContextDestroyed();
+        return '';
+      }
+    });
+    savedInspect(e);
+  `);
+
+  InspectorTest.log('Success (no crash).');
+  InspectorTest.completeTest();
+})();
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/test/inspector/runtime/regress-523442920-expected.txt b/test/inspector/runtime/regress-523442920-expected.txt
new file mode 100644
index 0000000..ac306d2
--- /dev/null
+++ b/test/inspector/runtime/regress-523442920-expected.txt
@@ -0,0 +1,2 @@
+Tests that destroying context during inspect does not cause UAF (regress-523442920).
+Success (no crash).
diff --git a/test/inspector/runtime/regress-523442920.js b/test/inspector/runtime/regress-523442920.js
new file mode 100644
index 0000000..d3442cd
--- /dev/null
+++ b/test/inspector/runtime/regress-523442920.js
@@ -0,0 +1,32 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+let {session, contextGroup, Protocol} =
+  InspectorTest.start('Tests that destroying context during inspect does not cause UAF (regress-523442920).');
+
+(async function test() {
+  await Protocol.Runtime.enable();
+
+  // Capture CommandLineAPI inspect function.
+  await Protocol.Runtime.evaluate({
+    expression: 'globalThis.savedInspect = inspect;',
+    includeCommandLineAPI: true,
+  });
+
+  // Call savedInspect from page-level execution where no ContextScope is active.
+  contextGroup.addScript(`
+    let e = new Error();
+    delete e.name;
+    Object.defineProperty(Object.getPrototypeOf(e), 'name', {
+      get() {
+        inspector.fireContextDestroyed();
+        return '';
+      }
+    });
+    savedInspect(e);
+  `);
+
+  InspectorTest.log('Success (no crash).');
+  InspectorTest.completeTest();
+})();
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.