Chrome · DevTools
CVE-2026-87617
UAF in DevTools
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
gettest/inspector/runtime/regress-523442920.js |
modified |
Files Changed
src/inspector/v8-console.cctest/inspector/runtime/regress-523442920-expected.txttest/inspector/runtime/regress-523442920.js
Patch
From 23294e43bec49915a9f3fb9f3b45acc559d1bd6e Mon Sep 17 00:00:00 2001
From: Yang Guo <yangguo@chromium.org>
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 <szuend@chromium.org>
Auto-Submit: Yang Guo <yangguo@chromium.org>
Reviewed-by: Simon Zünd <szuend@chromium.org>
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.
References
On This Page