CVE-2026-10989
Overview
Files Changed
src/inspector/v8-debugger-agent-impl.ccsrc/inspector/v8-runtime-agent-impl.cctest/inspector/regress/regress-crbug-516311623-expected.txttest/inspector/regress/regress-crbug-516311623.js
Patch
From 772a0f365b170021dd9ab2c6549a82c4a18501aa Mon Sep 17 00:00:00 2001
From: Simon Zünd <szuend@chromium.org>
Date: Tue, 26 May 2026 11:08:46 +0000
Subject: [PATCH] [inspector] Report a CDP error when installCommandLineAPI fails
Trying to install the command line API function fails on a frozen
globalThis with strict mode frames on the stack. We should gracefully
fail the CDP call in this case.
R=kimanh@chromium.org
Fixed: 516311623
Change-Id: Ib7b731f2d208ca2ccf932528fb3a9cf9b4ad9af5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7876001
Reviewed-by: Kim-Anh Tran <kimanh@chromium.org>
Commit-Queue: Simon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/main@{#107558}
---
diff --git a/src/inspector/v8-debugger-agent-impl.cc b/src/inspector/v8-debugger-agent-impl.cc
index cc5b275..b95f582 100644
--- a/src/inspector/v8-debugger-agent-impl.cc
+++ b/src/inspector/v8-debugger-agent-impl.cc
@@ -1725,7 +1725,13 @@
InjectedScript::CallFrameScope scope(m_session, callFrameId);
Response response = scope.initialize();
if (!response.IsSuccess()) return response;
- if (includeCommandLineAPI.value_or(false)) scope.installCommandLineAPI();
+
+ if (includeCommandLineAPI.value_or(false)) {
+ scope.installCommandLineAPI();
+ if (scope.tryCatch().HasCaught()) {
+ return Response::ServerError("Failed to install command line API");
+ }
+ }
if (silent.value_or(false)) scope.ignoreExceptionsAndMuteConsole();
int frameOrdinal = static_cast<int>(scope.frameOrdinal());
diff --git a/src/inspector/v8-runtime-agent-impl.cc b/src/inspector/v8-runtime-agent-impl.cc
index b8d6d44..e6ce30c 100644
--- a/src/inspector/v8-runtime-agent-impl.cc
+++ b/src/inspector/v8-runtime-agent-impl.cc
@@ -386,7 +386,14 @@
if (silent.value_or(false)) scope.ignoreExceptionsAndMuteConsole();
if (userGesture.value_or(false)) scope.pretendUserGesture();
- if (includeCommandLineAPI.value_or(false)) scope.installCommandLineAPI();
+ if (includeCommandLineAPI.value_or(false)) {
+ scope.installCommandLineAPI();
+ if (scope.tryCatch().HasCaught()) {
+ callback->sendFailure(
+ Response::ServerError("Failed to install command line API"));
+ return;
+ }
+ }
const bool replMode = maybeReplMode.value_or(false);
diff --git a/test/inspector/regress/regress-crbug-516311623-expected.txt b/test/inspector/regress/regress-crbug-516311623-expected.txt
new file mode 100644
index 0000000..717d571
--- /dev/null
+++ b/test/inspector/regress/regress-crbug-516311623-expected.txt
@@ -0,0 +1,24 @@
+Test that Runtime.evaluate with includeCommandLineAPI does not crash when global object is frozen.
+Running test: testStrictFrame
+Paused in strict mode.
+Evaluating with includeCommandLineAPI while paused in strict...
+{
+ error : {
+ code : -32000
+ message : Failed to install command line API
+ }
+ id : <messageId>
+}
+Running test: testSloppyFrame
+Paused in sloppy mode.
+Evaluating with includeCommandLineAPI while paused in sloppy...
+{
+ id : <messageId>
+ result : {
+ result : {
+ description : 4
+ type : number
+ value : 4
+ }
+ }
+}
diff --git a/test/inspector/regress/regress-crbug-516311623.js b/test/inspector/regress/regress-crbug-516311623.js
new file mode 100644
index 0000000..b083cd4
--- /dev/null
+++ b/test/inspector/regress/regress-crbug-516311623.js
@@ -0,0 +1,72 @@
+// 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.
+
+const {session, Protocol} = InspectorTest.start(
+ 'Test that Runtime.evaluate with includeCommandLineAPI does not crash when global object is frozen.');
+
+InspectorTest.runAsyncTestSuite([
+ async function testStrictFrame() {
+ await Protocol.Debugger.enable();
+
+ // Define both strict and sloppy mode functions upfront before freezing the global object.
+ await Protocol.Runtime.evaluate({
+ expression: `
+ const global = this;
+ function runStrict() {
+ "use strict";
+ Object.freeze(global);
+ debugger;
+ }
+ function runSloppy() {
+ debugger;
+ }
+ `
+ });
+
+ // Run the strict function. It should pause.
+ const pausedPromise = Protocol.Debugger.oncePaused();
+ Protocol.Runtime.evaluate({ expression: 'runStrict()' });
+ await pausedPromise;
+ InspectorTest.log('Paused in strict mode.');
+
+ // Evaluate with includeCommandLineAPI: true.
+ // In strict mode, the command line API installation throws TypeError.
+ // The evaluation aborts early and returns the TypeError object.
+ InspectorTest.log('Evaluating with includeCommandLineAPI while paused in strict...');
+ const evalResponse = await Protocol.Runtime.evaluate({
+ expression: '2 + 2',
+ includeCommandLineAPI: true
+ });
+
+ // Log the full response to see the error.
+ InspectorTest.logMessage(evalResponse);
+
+ await Protocol.Debugger.resume();
+ },
+
+ async function testSloppyFrame() {
+ // Note: Global is already frozen from the previous test.
+ // runSloppy is also already defined.
+
+ // Run the sloppy function. It should pause.
+ const pausedPromise = Protocol.Debugger.oncePaused();
+ Protocol.Runtime.evaluate({ expression: 'runSloppy()' });
+ await pausedPromise;
+ InspectorTest.log('Paused in sloppy mode.');
+
+ // Evaluate with includeCommandLineAPI: true.
+ // In sloppy mode, the command line API installation fails silently.
+ // The evaluation proceeds and returns 4.
+ InspectorTest.log('Evaluating with includeCommandLineAPI while paused in sloppy...');
+ const evalResponse = await Protocol.Runtime.evaluate({
+ expression: '2 + 2',
+ includeCommandLineAPI: true
+ });
+
+ // Log the full response, should be value: 4.
+ InspectorTest.logMessage(evalResponse);
+
+ await Protocol.Debugger.resume();
+ }
+]);
Regression Test / PoC
diff --git a/test/inspector/regress/regress-crbug-516311623-expected.txt b/test/inspector/regress/regress-crbug-516311623-expected.txt
new file mode 100644
index 0000000..717d571
--- /dev/null
+++ b/test/inspector/regress/regress-crbug-516311623-expected.txt
@@ -0,0 +1,24 @@
+Test that Runtime.evaluate with includeCommandLineAPI does not crash when global object is frozen.
+Running test: testStrictFrame
+Paused in strict mode.
+Evaluating with includeCommandLineAPI while paused in strict...
+{
+ error : {
+ code : -32000
+ message : Failed to install command line API
+ }
+ id : <messageId>
+}
+Running test: testSloppyFrame
+Paused in sloppy mode.
+Evaluating with includeCommandLineAPI while paused in sloppy...
+{
+ id : <messageId>
+ result : {
+ result : {
+ description : 4
+ type : number
+ value : 4
+ }
+ }
+}
diff --git a/test/inspector/regress/regress-crbug-516311623.js b/test/inspector/regress/regress-crbug-516311623.js
new file mode 100644
index 0000000..b083cd4
--- /dev/null
+++ b/test/inspector/regress/regress-crbug-516311623.js
@@ -0,0 +1,72 @@
+// 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.
+
+const {session, Protocol} = InspectorTest.start(
+ 'Test that Runtime.evaluate with includeCommandLineAPI does not crash when global object is frozen.');
+
+InspectorTest.runAsyncTestSuite([
+ async function testStrictFrame() {
+ await Protocol.Debugger.enable();
+
+ // Define both strict and sloppy mode functions upfront before freezing the global object.
+ await Protocol.Runtime.evaluate({
+ expression: `
+ const global = this;
+ function runStrict() {
+ "use strict";
+ Object.freeze(global);
+ debugger;
+ }
+ function runSloppy() {
+ debugger;
+ }
+ `
+ });
+
+ // Run the strict function. It should pause.
+ const pausedPromise = Protocol.Debugger.oncePaused();
+ Protocol.Runtime.evaluate({ expression: 'runStrict()' });
+ await pausedPromise;
+ InspectorTest.log('Paused in strict mode.');
+
+ // Evaluate with includeCommandLineAPI: true.
+ // In strict mode, the command line API installation throws TypeError.
+ // The evaluation aborts early and returns the TypeError object.
+ InspectorTest.log('Evaluating with includeCommandLineAPI while paused in strict...');
+ const evalResponse = await Protocol.Runtime.evaluate({
+ expression: '2 + 2',
+ includeCommandLineAPI: true
+ });
+
+ // Log the full response to see the error.
+ InspectorTest.logMessage(evalResponse);
+
+ await Protocol.Debugger.resume();
+ },
+
+ async function testSloppyFrame() {
+ // Note: Global is already frozen from the previous test.
+ // runSloppy is also already defined.
+
+ // Run the sloppy function. It should pause.
+ const pausedPromise = Protocol.Debugger.oncePaused();
+ Protocol.Runtime.evaluate({ expression: 'runSloppy()' });
+ await pausedPromise;
+ InspectorTest.log('Paused in sloppy mode.');
+
+ // Evaluate with includeCommandLineAPI: true.
+ // In sloppy mode, the command line API installation fails silently.
+ // The evaluation proceeds and returns 4.
+ InspectorTest.log('Evaluating with includeCommandLineAPI while paused in sloppy...');
+ const evalResponse = await Protocol.Runtime.evaluate({
+ expression: '2 + 2',
+ includeCommandLineAPI: true
+ });
+
+ // Log the full response, should be value: 4.
+ InspectorTest.logMessage(evalResponse);
+
+ await Protocol.Debugger.resume();
+ }
+]);
Original Bug Report
DCHECK failure in !isolate->has_exception() in execution.cc
Detailed Report: https://clusterfuzz.com/testcase?key=4548820230766592
Fuzzer: ochang_js_fuzzer Job Type: linux_asan_d8_dbg Platform Id: linux
Crash Type: DCHECK failure Crash Address: Crash State: !isolate->has_exception() in execution.cc v8::internal::Invoke v8::internal::Execution::CallScript
Sanitizer: address (ASAN)
Regressed: https://clusterfuzz.com/revisions?job=linux_asan_d8_dbg&range=91856:91857
Reproducer Testcase: https://clusterfuzz.com/download?testcase_id=4548820230766592
Issue filed automatically.
To reproduce this, please build the target in this report and run it against the reproducer testcase. Please use the GN arguments provided at bottom of this report when building the binary.
If you have trouble reproducing, please also export the environment variables listed under “[Environment]” in the crash stacktrace.
If you have any feedback on reproducing test cases, let us know at https://forms.gle/Yh3qCYFveHj6E5jz5 so we can improve.