Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactImproper input validation in DevTools
DescriptionImproper input validation in DevTools
ComponentDevTools
Bug ClassLogic Error
Tracker532182486
Fix commita4da52b13493 (chromium/src) +12/-6
CISA KEVNot listed
CreditedGoogle
Disclosed2026-08-25

Files Changed

  • content/browser/devtools/devtools_session.cc
From a4da52b13493517489a31a03a7f3fc8744422544 Mon Sep 17 00:00:00 2001
From: Johannes Henkel <johannes@chromium.org>
Date: Wed, 08 Jul 2026 09:01:10 -0700
Subject: [PATCH] Add an explicit check for the absence of sessionId for root session.

Bug: 532182486
Change-Id: Iae09d971b7c2f895f8f7269e26a568b0f4c236e4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8058008
Commit-Queue: Johannes Henkel <johannes@chromium.org>
Reviewed-by: Alex Rudenko <alexrudenko@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1658807}
---

diff --git a/content/browser/devtools/devtools_session.cc b/content/browser/devtools/devtools_session.cc
index 2ebf82b5..b3f7a67c 100644
--- a/content/browser/devtools/devtools_session.cc
+++ b/content/browser/devtools/devtools_session.cc
@@ -794,18 +794,18 @@
     }
   }
 
-  // Do NOT use crdtp::Dispatchable here. It enforces the presence of both
-  // 'id' and 'method', which are not guaranteed in Responses and Notifications.
-  crdtp::span<uint8_t> extracted_session_id =
-      crdtp::cbor::GetString8ValueFromMap(span_message,
-                                          crdtp::SpanFrom("sessionId"));
-
   if (!expected_has_id &&
       crdtp::cbor::HasKeyInMap(span_message, crdtp::SpanFrom("id"))) {
     DLOG(ERROR) << "Expected no id in the message but received one";
     return false;
   }
 
+  // Do NOT use crdtp::Dispatchable here. It enforces the presence of both
+  // 'id' and 'method', which are not guaranteed in Responses and Notifications.
+  crdtp::span<uint8_t> extracted_session_id =
+      crdtp::cbor::GetString8ValueFromMap(span_message,
+                                          crdtp::SpanFrom("sessionId"));
+
   if (expected_session_id.empty()) {
     if (!extracted_session_id.empty()) {
       DLOG(ERROR) << "Root session expected no sessionId but received one: "
@@ -815,6 +815,12 @@
                                         extracted_session_id.end()));
       return false;
     }
+    // This additional check is necessary since GetString8ValueFromMap returns
+    // the empty span when encountering duplicate entries.
+    if (crdtp::cbor::HasKeyInMap(span_message, crdtp::SpanFrom("sessionId"))) {
+      DLOG(ERROR) << "Root session expected no sessionId but received dupes.";
+      return false;
+    }
     return true;
   }
   if (extracted_session_id.empty() ||
Loading diff…

Original Bug Report

reported by rj...@google.com

Protocol Smuggling in DevTools via Duplicate CBOR Keys

Flapjack has identified a security issue and generated a PoC.

Build variant: Default

Build arguments: v8_enable_sandbox=true v8_enable_memory_corruption_api=true

Shell command: d8 --run-as-security-poc --enable-inspector --omit-quit --disable-in-process-stack-traces

Return code: 134

<details>

<summary>stdout</summary>

</details>

<details>

<summary>stderr</summary>

#
# Fatal error in ../../v8/src/inspector/v8-inspector-session-impl.cc, line 193
# Check failed: ConvertCBORToJSON(SpanFrom(cbor), &json).ok().
#
#
#
#FailureMessage Object: 0x7ffd7ab0fad0
==== C stack trace ===============================

    /home/rjlothian_google_com/chromium_ro/src/out/Default/libv8_libbase.so(v8::base::debug::StackTrace::StackTrace()+0x1e) [0x7e696560c08e]
    /home/rjlothian_google_com/chromium_ro/src/out/Default/libv8_libplatform.so(+0x16c6d) [0x7e6965594c6d]
    /home/rjlothian_google_com/chromium_ro/src/out/Default/libv8_libbase.so(V8_Fatal(char const*, int, char const*, ...)+0x194) [0x7e69655ee074]
    /home/rjlothian_google_com/chromium_ro/src/out/Default/libv8.so(+0x46c8bf2) [0x7e69632c8bf2]
    /home/rjlothian_google_com/chromium_ro/src/out/Default/libv8.so(+0x46c8c59) [0x7e69632c8c59]
    /home/rjlothian_google_com/chromium_ro/src/out/Default/libv8.so(+0x46f3bcc) [0x7e69632f3bcc]
    /home/rjlothian_google_com/chromium_ro/src/out/Default/libv8.so(+0x46f3aa9) [0x7e69632f3aa9]
    /home/rjlothian_google_com/chromium_ro/src/out/Default/libv8.so(+0x4663a06) [0x7e6963263a06]
    /home/rjlothian_google_com/chromium_ro/src/out/Default/libv8.so(+0x46d19de) [0x7e69632d19de]
    /home/rjlothian_google_com/chromium_ro/src/out/Default/libv8.so(+0x465f501) [0x7e696325f501]
    /home/rjlothian_google_com/chromium_ro/src/out/Default/libv8.so(+0x465e263) [0x7e696325e263]
    /home/rjlothian_google_com/chromium_ro/src/out/Default/libv8.so(+0x46f4396) [0x7e69632f4396]
    /home/rjlothian_google_com/chromium_ro/src/out/Default/libv8.so(+0x46c9d78) [0x7e69632c9d78]
    /home/rjlothian_google_com/chromium_ro/src/out/Default/d8(+0xaa288) [0x5f05ebf05288]
    /home/rjlothian_google_com/chromium_ro/src/out/Default/libv8.so(+0x140ef60) [0x7e696000ef60]

</details>

Overview: A logic error in the CRDTP CBOR parser allows a compromised renderer to bypass DevTools session ID validation by using duplicate keys. The browser treats duplicate sessionId keys as absent, while downstream consumers apply a “last-key-wins” policy. This enables the renderer to spoof messages for other multiplexed DevTools sessions.

Affected files:

  • third_party/inspector_protocol/crdtp/cbor.cc
  • content/browser/devtools/devtools_session.cc
  • v8/third_party/inspector_protocol/crdtp/cbor.cc

Estimated timestamp from git blame: 2026-05-18

Root Cause

In third_party/inspector_protocol/crdtp/cbor.cc, the utility function GetString8ValueFromMap is used to quickly extract a string value from a CBOR map. If it encounters the target key more than once, it returns an empty span:

    if (is_key) {
      if (tokenizer.TokenTag() == CBORTokenTag::STRING8 &&
          SpanEquals(tokenizer.GetString8(), string8_key)) {
        if (found_key) {
          return {};  // Duplicate key returns empty span
        }
        found_key = true;
      }
    }

In content/browser/devtools/devtools_session.cc, DevToolsSession::ValidateMessage uses this function to extract the sessionId from incoming protocol messages from the renderer. For the root DevTools session, the expected_session_id is empty. If the extracted session ID is empty, validation passes:

  if (expected_session_id.empty()) {
    if (!extracted_session_id.empty()) {
      return false;
    }
    return true; // Passes if empty span is returned
  }

Impact

An attacker in a compromised renderer (acting as the root DevTools session) can craft a message with duplicate sessionId keys. Because GetString8ValueFromMap returns an empty span upon encountering the duplicate, the browser’s validator incorrectly assumes the message lacks a session ID and accepts it as valid for the root session.

The browser then forwards the unmodified message to the DevTools frontend (or an automation client). These downstream consumers typically parse the message using JSON (JSON.parse()) or other parsers that follow a “last-key-wins” policy. Consequently, the client processes the message using the smuggled sessionId, allowing the compromised renderer to spoof responses and notifications for arbitrary DevTools sessions (such as cross-origin iframes) multiplexed on the same connection. This completely breaks the DevTools session isolation boundary.

Suggested Fix

Modify GetString8ValueFromMap to explicitly signal a parsing error when duplicate keys are encountered, rather than silently returning an empty span (which is indistinguishable from a missing key). This could be achieved by changing its return type to crdtp::StatusOr<span<uint8_t>>, allowing ValidateMessage to fail validation and drop the message if a Status indicating a duplicate key is returned.

Evaluated with Chrome root at commit: e90946bb1b0c143a02180dd070c9ce75d4d0b935


The description of the vuln is LLM-generated and can contain mistakes. Your feedback is appreciated, and will help us make improvement over time. The PoC was run in a VM and it seemed to be legit - if not, let us know and we can strengthen our checker. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

View on issue tracker