Chrome · DevTools
CVE-2026-87511
Logic Error in DevTools
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifsrc/inspector/v8-inspector-session-impl.cc |
modified |
Files Changed
src/inspector/v8-console.ccsrc/inspector/v8-inspector-session-impl.cctest/inspector/cpu-profiler/untrusted-session-expected.txttest/inspector/cpu-profiler/untrusted-session.js
Patch
From 01087f5f8f921c5f55f8f6bda4132d48f5eba0e7 Mon Sep 17 00:00:00 2001
From: Philip Pfaffe <pfaffe@chromium.org>
Date: Wed, 05 Aug 2026 13:55:02 +0000
Subject: [PATCH] Require fully trusted clients for the inspector profiler
Fixed: 513395384
Change-Id: Icc180358092f354a7e719ae3aad807249b2a95c9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/8203445
Reviewed-by: Simon Zünd <szuend@chromium.org>
Commit-Queue: Philip Pfaffe <pfaffe@chromium.org>
Cr-Commit-Position: refs/heads/main@{#109069}
---
diff --git a/src/inspector/v8-console.cc b/src/inspector/v8-console.cc
index 88d0da1..0fa7caf 100644
--- a/src/inspector/v8-console.cc
+++ b/src/inspector/v8-console.cc
@@ -389,7 +389,9 @@
String16 title =
toProtocolString(m_inspector->isolate(), helper.firstArgToString());
helper.forEachSession([&title](V8InspectorSessionImpl* session) {
- session->profilerAgent()->consoleProfile(title);
+ if (session->profilerAgent()) {
+ session->profilerAgent()->consoleProfile(title);
+ }
});
TRACE_EVENT_END(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "title",
title.utf8().c_str());
@@ -403,7 +405,9 @@
String16 title =
toProtocolString(m_inspector->isolate(), helper.firstArgToString());
helper.forEachSession([&title](V8InspectorSessionImpl* session) {
- session->profilerAgent()->consoleProfileEnd(title);
+ if (session->profilerAgent()) {
+ session->profilerAgent()->consoleProfileEnd(title);
+ }
});
TRACE_EVENT_END(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "title",
title.utf8().c_str());
diff --git a/src/inspector/v8-inspector-session-impl.cc b/src/inspector/v8-inspector-session-impl.cc
index e7d788d..99271ac 100644
--- a/src/inspector/v8-inspector-session-impl.cc
+++ b/src/inspector/v8-inspector-session-impl.cc
@@ -138,11 +138,11 @@
this, this, agentState(protocol::Console::Metainfo::domainName)));
protocol::Console::Dispatcher::wire(&m_dispatcher, m_consoleAgent.get());
- m_profilerAgent.reset(new V8ProfilerAgentImpl(
- this, this, agentState(protocol::Profiler::Metainfo::domainName)));
- protocol::Profiler::Dispatcher::wire(&m_dispatcher, m_profilerAgent.get());
-
if (m_clientTrustLevel == V8Inspector::kFullyTrusted) {
+ m_profilerAgent.reset(new V8ProfilerAgentImpl(
+ this, this, agentState(protocol::Profiler::Metainfo::domainName)));
+ protocol::Profiler::Dispatcher::wire(&m_dispatcher, m_profilerAgent.get());
+
m_heapProfilerAgent.reset(new V8HeapProfilerAgentImpl(
this, this, agentState(protocol::HeapProfiler::Metainfo::domainName)));
protocol::HeapProfiler::Dispatcher::wire(&m_dispatcher,
@@ -156,7 +156,7 @@
m_runtimeAgent->restore();
m_debuggerAgent->restore();
if (m_heapProfilerAgent) m_heapProfilerAgent->restore();
- m_profilerAgent->restore();
+ if (m_profilerAgent) m_profilerAgent->restore();
m_consoleAgent->restore();
}
}
@@ -165,7 +165,7 @@
v8::Isolate::Scope scope(m_inspector->isolate());
discardInjectedScripts();
m_consoleAgent->disable();
- m_profilerAgent->disable();
+ if (m_profilerAgent) m_profilerAgent->disable();
if (m_heapProfilerAgent) m_heapProfilerAgent->disable();
m_debuggerAgent->disable();
m_runtimeAgent->disable();
@@ -442,18 +442,20 @@
.setName(protocol::Debugger::Metainfo::domainName)
.setVersion(protocol::Debugger::Metainfo::version)
.build());
- result.push_back(protocol::Schema::Domain::create()
- .setName(protocol::Profiler::Metainfo::domainName)
- .setVersion(protocol::Profiler::Metainfo::version)
- .build());
- result.push_back(protocol::Schema::Domain::create()
- .setName(protocol::HeapProfiler::Metainfo::domainName)
- .setVersion(protocol::HeapProfiler::Metainfo::version)
- .build());
- result.push_back(protocol::Schema::Domain::create()
- .setName(protocol::Schema::Metainfo::domainName)
- .setVersion(protocol::Schema::Metainfo::version)
- .build());
+ if (m_clientTrustLevel == V8Inspector::kFullyTrusted) {
+ result.push_back(protocol::Schema::Domain::create()
+ .setName(protocol::Profiler::Metainfo::domainName)
+ .setVersion(protocol::Profiler::Metainfo::version)
+ .build());
+ result.push_back(protocol::Schema::Domain::create()
+ .setName(protocol::HeapProfiler::Metainfo::domainName)
+ .setVersion(protocol::HeapProfiler::Metainfo::version)
+ .build());
+ result.push_back(protocol::Schema::Domain::create()
+ .setName(protocol::Schema::Metainfo::domainName)
+ .setVersion(protocol::Schema::Metainfo::version)
+ .build());
+ }
return result;
}
@@ -521,7 +523,9 @@
void V8InspectorSessionImpl::triggerPreciseCoverageDeltaUpdate(
StringView occasion) {
- m_profilerAgent->triggerPreciseCoverageDeltaUpdate(toString16(occasion));
+ if (m_profilerAgent) {
+ m_profilerAgent->triggerPreciseCoverageDeltaUpdate(toString16(occasion));
+ }
}
V8InspectorSession::EvaluateResult V8InspectorSessionImpl::evaluate(
diff --git a/test/inspector/cpu-profiler/untrusted-session-expected.txt b/test/inspector/cpu-profiler/untrusted-session-expected.txt
new file mode 100644
index 0000000..eb29fc0
--- /dev/null
+++ b/test/inspector/cpu-profiler/untrusted-session-expected.txt
@@ -0,0 +1,3 @@
+Tests that Profiler domain is not available in untrusted session.
+console.profile in untrusted session did not crash.
+Error: Called non-existent method. 'Profiler.enable' wasn't found code: -32601
diff --git a/test/inspector/cpu-profiler/untrusted-session.js b/test/inspector/cpu-profiler/untrusted-session.js
new file mode 100644
index 0000000..47c1b2c
--- /dev/null
+++ b/test/inspector/cpu-profiler/untrusted-session.js
@@ -0,0 +1,20 @@
+// 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.
+
+InspectorTest.start(
+ 'Tests that Profiler domain is not available in untrusted session.');
+
+(async () => {
+ const contextGroup = new InspectorTest.ContextGroup();
+ const session = contextGroup.connect(/* isFullyTrusted */ false);
+ const {Protocol} = session;
+
+ await Protocol.Runtime.evaluate({
+ expression: 'console.profile("test"); console.profileEnd("test");'
+ });
+ InspectorTest.log('console.profile in untrusted session did not crash.');
+ await Protocol.Profiler.enable();
+
+ 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