CVE-2026-7937
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
iffront_end/Tests.js |
modified |
Files Changed
front_end/Tests.js
Patch
From 5b4a14ceeeb42f9d14815501ffb066915889406b Mon Sep 17 00:00:00 2001 From: Danil Somsikov <[email protected]> Date: Thu, 26 Mar 2026 12:56:19 -0700 Subject: [PATCH] Handle test output messages that arrive before the waiter is ready. The waitForTestResultsAsMessage function now buffers test output messages received via top.postMessage in earlyTestResults if the waiter is not yet active. This prevents missing test results that are posted very quickly after the test starts. When waitForTestResultsAsMessage is called, it first checks the buffer before setting up a waiter. Bug: 491766258 Change-Id: Ib34bb6e87ab1036e1c52ecbcd057050dc490fe7b Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/7704616 Reviewed-by: Andrey Kosyakov <[email protected]> Commit-Queue: Danil Somsikov <[email protected]> Auto-Submit: Danil Somsikov <[email protected]> Commit-Queue: Andrey Kosyakov <[email protected]> --- diff --git a/front_end/Tests.js b/front_end/Tests.js index 7688a87..6a13544 100644 --- a/front_end/Tests.js +++ b/front_end/Tests.js @@ -1086,20 +1086,36 @@ this.takeControl({slownessFactor: 10}); }; - TestSuite.prototype.waitForTestResultsAsMessage = function() { - const onMessage = event => { - if (!event.data.testOutput) { - return; - } - top.removeEventListener('message', onMessage); + const earlyTestResults = []; + let testResultsWaiter = null; + + top.addEventListener('message', event => { + if (event.data && event.data.testOutput) { const text = event.data.testOutput; + if (testResultsWaiter) { + testResultsWaiter(text); + } else { + earlyTestResults.push(text); + } + } + }); + + TestSuite.prototype.waitForTestResultsAsMessage = function() { + const handleMessage = text => { + testResultsWaiter = null; if (text === 'PASS') { this.releaseControl(); } else { this.fail(text); } }; - top.addEventListener('message', onMessage); + + if (earlyTestResults.length) { + handleMessage(earlyTestResults.shift()); + return; + } + + testResultsWaiter = handleMessage; this.takeControl(); };
Original Bug Report
Extensions without file URL access can use the `Page.navigate` CDP command to open `view-source:file:` URLs
VULNERABILITY DETAILS
Summary
A malicious extension can use the chrome.debugger.sendCommand API with the Page.navigate CDP command to navigate to view-source:file: URLs without the user enabling Allow access to file URLs. On Windows, this can be exploited using a UNC path to leak NTLM hashes to an attacker-controlled server.
Attack Preconditions
The victim installs a malicious extension provided by the attacker, or a legitimate extension has a vulnerability that allows an attacker to control the URL passed to the Page.navigate CDP command.
Impact Analysis
On Windows, the attacker can set up a server to capture NTLM hashes leaked via a view-source:file: URL using a UNC path, similar to bugs like Issue 391114799 and Issue 40060207. After acquiring the NTLM hashes, the attacker can perform offline cracking or use them with other techniques to gain access to Active Directory-based networks.
On macOS and Linux, the impact might be limited since I couldn’t find a way to leak the page content of a view-source:file: URL without file URL access permissions.
Bisect and Root Cause Analysis
Unlike IsFileUrl, which correctly checks for view-source: URLs and unwraps them to check the inner URL’s scheme, PageHandler::Navigate doesn’t unwrap view-source: URL to check the inner URL’s scheme. This allows view-source:file: URLs to be navigated to without file URL access permission:
if (gurl.SchemeIsFile() && !may_read_local_files_) {
callback->sendFailure(
Response::ServerError("Navigating to local URL is not allowed"));
return;
}
The check for file URLs was introduced in this commit:
https://source.chromium.org/chromium/chromium/src/+/925a1926434ee8e71b7adac47989df27e64b69d6
VERSION
Chrome Version: 145.0.7632.76 stable
Operating System: Linux, Mac, Windows
This vulnerability is also present in Chrome 147.0.7727.0 canary.
REPRODUCTION CASE
- Set up Responder for catching NTLM hashes. The server can be set up with the installation guide provided in the repository or set up with Docker as follows (make sure to replace
<INTERFACE>with the actual network interface you want to listen on):docker run --rm -ti --network host kalilinux/kali-rolling # Inside the container apt update && apt install -y responder responder -v -I <INTERFACE> - Create a directory structure like this with the attached file:
poc ├── background.js └── manifest.json - Replace
<YOUR IP>inbackground.jswith the actual IP address of your machine where Responder is running. - Load the extension in Chrome by navigating to
chrome://extensions, enablingDeveloper mode, and clickingLoad unpacked. Select thepocdirectory. - Disable the
Allow access to file URLsoption for the extension inchrome://extensionsto make sure the PoC is running without the permission. - After disabling the permission, the
background.jsscript should reload and usechrome.debugger.sendCommandAPI withPage.navigateCDP command to navigate to theview-source:file:////<YOUR IP>/leakURL. - Even though the extension doesn’t have the permission to access file URLs,
Page.navigateshould still successfully navigate the tab to theview-source:file:URL. - You should see the NTLM hashes being captured in the console output of Responder.
> Note: To simply prove that navigation to view-source:file: URLs works without file URL access, instead of using UNC path, you can update TARGET_URL in background.js to use something like view-source:file:///etc/hosts on Linux/macOS or view-source:file:///C:/Windows/System32/drivers/etc/hosts on Windows to see if the URL can be loaded without file URL access permissions. The reproduction steps above are specifically for demonstrating the NTLM hash leak on Windows.
CREDIT INFORMATION
Reporter credit: lebr0nli of National Yang Ming Chiao Tung University, Dept. of CS, Security and Systems Lab.
- https://github.com/lgandx/Responder
- https://issuetracker.google.com/issues/391114799
- https://issuetracker.google.com/issues/40060207
- https://source.chromium.org/chromium/chromium/src/+/925a1926434ee8e71b7adac47989df27e64b69d6
- https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/extensions/extension_tab_util.cc;l=140-143;drc=152d856fc77c3ba05f9fe3261dbc745c73b63333
- https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/protocol/page_handler.cc;l=878-882;drc=e2a6aae100f3db23e9540c326e910488473ec419