CVE-2025-13097
Overview
Files Changed
AUTHORSfront_end/core/host/InspectorFrontendHost.ts
Patch
From b2de95f7786a65c28bb10b11f171b82dfc13d054 Mon Sep 17 00:00:00 2001
From: Alesandro Ortiz <alesandro@alesandroortiz.com>
Date: Thu, 13 Mar 2025 20:09:10 +0000
Subject: [PATCH] Check URL scheme in `InspectorFrontendHost.openInNewTab()`
Fixed: 402791076
Change-Id: I40651dd32e797a67cb7e46c9a060cfcc6fb6d50b
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6353071
Reviewed-by: Danil Somsikov <dsv@chromium.org>
Reviewed-by: Philip Pfaffe <pfaffe@chromium.org>
Commit-Queue: Alesandro Ortiz <alesandro@alesandroortiz.com>
---
diff --git a/AUTHORS b/AUTHORS
index 7fa474e..4d5c2a1 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -13,6 +13,7 @@
# BEGIN individuals section.
AbdAlRahman Gad <abdobngad@gmail.com>
Ajay Panthagani <ajaypanthagani321@gmail.com>
+Alesandro Ortiz <alesandro@alesandroortiz.com>
Alexander Stammbach <alexander@stammbach.io>
Alexey Rodionov <fluorescent.hallucinogen@gmail.com>
Ankit Mishra <ankit.mishra131990@gmail.com>
diff --git a/front_end/core/host/InspectorFrontendHost.ts b/front_end/core/host/InspectorFrontendHost.ts
index 20f176c..71bb258 100644
--- a/front_end/core/host/InspectorFrontendHost.ts
+++ b/front_end/core/host/InspectorFrontendHost.ts
@@ -187,6 +187,9 @@
}
openInNewTab(url: Platform.DevToolsPath.UrlString): void {
+ if (Common.ParsedURL.schemeIs(url, 'javascript:')) {
+ return;
+ }
window.open(url, '_blank');
}
Original Bug Report
Security: DevTools XSS allows sandbox escape, UXSS, CDP access, other impacts
SUMMARY
This is a variation of issue 40942152 due to incomplete fix.
With devtools://devtools/bundled/integration_test_runner.html connected to a malicious remote WebSocket server, after user double-clicks on a network log item, an attacker can run JavaScript in devtools://devtools origin.
Impacts include universal XSS, browser sandbox escape by opening downloaded file, local file read, user interaction requirements bypass, and access to most CDP commands.
Initial report has PoCs for browser sandbox escape initiated from web page. I will provide the other PoCs once I’ve cleaned them up, including extension PoCs that reduce user interaction.
VULNERABILITY DETAILS
devtools:// URLs can be opened with drag-and-drop from any page, or automatically by an extension with devtools_page in manifest or debugger permission.
devtools://devtools/bundled/integration_test_runner.html renders data provided by the WebSocket server specified via ?ws= param [1], including remotely-hosted WS servers.
A malicious WS server can generate network log rows for a resource with a javascript: URL. Double-clicking [2] a network log row will call InspectorFrontendHost.openInNewTab() [3] which calls window.open(url, '_blank') [4] with the URL of the resource, in this case the javascript: URL. (Right-clicking the row and selecting Open in new tab works similarly.)
Because integration_test_runner.html does not have CSP, the JS runs in a new window with the devtools://devtools origin. At this point, attacker can read/write to localStorage and set console pins. We then ask the user to press F12 to run the malicious console pins, which perform the rest of the attack. After the keypress, we also download the file we want to open (this download can occur at any point during the attack).
Because devtools:// pages cannot directly navigate to chrome:// URLs, the console pins will navigate to the PDF component extension (chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/pdf_viewer_wrapper.js), then use the extension’s chrome.tabs API to navigate to chrome://downloads, then execute JS in chrome://downloads to open the download.
In the provided PoCs, we then clean up the attack by deleting the malicious console pins, and either closing tabs or navigating tabs to benign pages.
Opening a downloaded file requires [5] a user interaction within the past 5 seconds, tracked per-tab using WebContentsImpl::last_interaction_time_ [6]. In faster devices, this is satisified by the earlier F12 keypress because the attack takes less than 5 seconds (see Scenario 1a). For 100% reliability, particularly on slower devices, we can generate a user interaction using CDP Input.* commands immediately before the file open attempt (see Scenario 1b).
Impacts
Immediately after initial XSS:
- Local file read: Read local files and directories with
DevToolsUIBindings::LoadNetworkResource()[7] (which is handler ofloadNetworkResourcemessage sent throughDevToolsHost.sendMessageToEmbedder()). - Set console pins: UXSS where DevTools is opened in the future, used for further impacts
After opening DevTools with malicious console pins:
- Sandbox escape by opening downloaded file: See main vuln description.
- UXSS: We can navigate current tab to any page and execute arbitrary JS regardless of CSP.
- Open DevTools-on-DevTools to gain CDP access: We can open
chrome://inspectand run JS to inspect the current DevTools instance (i.e. DevTools-on-Devtools), used for further impacts
After obtaining CDP access via DevTools-on-DevTools:
- Interaction requirement bypasses: We can send CDP
Input.*commands to simulate user interaction and bypass user interaction restrictions. - Parallel UXSS via CDP: For more efficient attacks, we can open multiple tabs and attack each of them simultaneously via CDP.
- Do anything else interesting with CDP against any listed target
[4] InspectorFrontendHost.openInNewTab() https://source.chromium.org/chromium/chromium/src/+/main:third_party/devtools-frontend/src/front_end/core/host/InspectorFrontendHost.ts;l=190;drc=4ab8cec6e9a5640f553f44afeec821b9e7050eb9
[5] DownloadsDOMHandler::OpenFileRequiringGesture() https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/webui/downloads/downloads_dom_handler.cc;l=244;drc=b37413daa8803e67405b635419ab665e0374a093
[6] WebContentsImpl::last_interaction_time_ https://source.chromium.org/chromium/chromium/src/+/main:content/browser/web_contents/web_contents_impl.h;l=2380;drc=ebb421b7cdc02be3ee4abf49d6bad7646b3da9ab
[7] DevToolsUIBindings::LoadNetworkResource() https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/devtools/devtools_ui_bindings.cc;l=1100;drc=de65c59454bb29fff1e642fb3528cd2c80e52fb4
ADDITIONAL CONTEXT
Reduction of attack user interactions
For extensions with devtools_page in manifest, we can open devtools:// URLs automatically. For extensions with debugger permission, most steps are automatic. I’ll provide extension PoCs in comments.
Other ways to reach openInNewTab()
While we use the Network panel to exploit this, any other usage of InspectorFrontendHost.openInNewTab() [4] is also vulnerable if attacker controls the URL (see Code Search [4]). Double clicking on network log row seemed like the easiest way to exploit.
VERSION
Verified repro on these versions:
Chrome Version: 134.0.6998.37 Stable, 135.0.7049.17 Beta, 136.0.7052.2 Dev, 136.0.7065.0 Canary
Operating System: Windows 10 (should repro for all desktop platforms)
PROPOSED PATCH
InspectorFrontendHost.openInNewTab() has many call sites. For example, most Linkfier methods call it but don’t check for unsafe schemes except for Linkifier::linkifyURL() [1]. There are other ways to reach openInNewTab() outside of Linkifier.
To ensure all current and future call sites are protected, adding the scheme check in InspectorFrontendHost.openInNewTab(), right before the window.open() call, seems like the best approach. AFAICT none of the current callers have a legitimate need to pass JS URLs.
I’ll upload a CL within a day or so.
BISECT
Had to do two bisects for the DevTools XSS. Earliest repro is Feb 2018 with inspector.html.
-
For
integration_test_runner.html:
Bisected to https://chromium.googlesource.com/devtools/devtools-frontend.git/+/9327dc31d27d2a5061636ce35e726dfd755a6dd3 (Mar 2021)
integration_test_runner.htmlfails to load a JS file before then, so PoC fails. But you can usedevtools_app.htmlas shown in second bisect.
Thedevtools-frontendcommit above was rolled into Chromium in https://crrev.com/ab3bc54ec9d1e6204ff73d71e4390903842af64b -
For
devtools_app.html/inspector.html(and probably other “production” entrypoints):
Bisected to https://crrev.com/abbb84580486221060a05e452652e045086ebc6c (Feb 2018) whenunsafe-inlinewas added to CSP. Repro’d withchrome-devtools://devtools/bundled/inspector.html.
Stopped reproducing in https://chromium.googlesource.com/devtools/devtools-frontend.git/+/1e2c0032dae51afc104b525b621ad723c0501361 (Oct 2021) whenunsafe-inlinewas removed for the non-test entrypoints.
REPRODUCTION CASE
Additional PoCs will be provided in the coming days.
One-time setup for WebSocket server:
- Download
package.jsonandwebsocket-server.js - Run
npm ito install dependency - Set desired port in source code (default
1337)
Setup for each scenario:
- Host per-scenario payload remotely or locally. Payload must be served with
Access-Control-Allow-Origin: *andContent-Type: text/javascriptheaders. - Update WebSocket server source to point to per-scenario payload URL.
- Run attacker WebSocket server with
node websocket-server.js, remotely or locally.
Scenario 1a: Sandbox escape via download
Payload: devtools-xss-download-sandbox-escape-1a
This depends on the automated steps occuring within 5 seconds. In slower devices, scenario 1b may be needed for 100% reliability.
Repro steps:
- Navigate to https://alesandroortiz.com/security/chromium/devtools-drag.html?ws=host:port (replace
host:portwith your WS server) - Drag the icon to a new tab (or existing tab)
- Double-click where DevTools says “CLICK TWICE HERE” to run JS payload (after this step, we have initial XSS with some impacts)
- Press F12 when prompted, then wait a few moments
Observed: JavaScript runs in devtools://devtools origin. Downloaded file is opened.
Expected: JavaScript is blocked from executing in any devtools:// origin. Downloaded file is not opened.
Scenario 1b: Sandbox escape via download + generated user interaction via CDP
Payload: devtools-xss-download-sandbox-escape-1b
Optional: To verify that this PoC does not depend on user interaction, set simulateDelayedLoading to true in payload.
Same impacts as 1a, but with 100% reliability because it uses DevTools-on-DevTools to access CDP and generate user interaction.
Repro steps: Same as scenario 1a (with different payload).
Observed/Expected: Same as scenario 1a.
Credit Information
Reporter credit: Alesandro Ortiz https://AlesandroOrtiz.com and Daniel Fröjdendahl https://FrojdenSec.com
- https://AlesandroOrtiz.com
- https://FrojdenSec.com
- https://alesandroortiz.com/security/chromium/devtools-drag.html?ws=host:port
- https://chromium.googlesource.com/devtools/devtools-frontend.git/+/1e2c0032dae51afc104b525b621ad723c0501361
- https://chromium.googlesource.com/devtools/devtools-frontend.git/+/9327dc31d27d2a5061636ce35e726dfd755a6dd3
- https://crrev.com/ab3bc54ec9d1e6204ff73d71e4390903842af64b
- https://crrev.com/abbb84580486221060a05e452652e045086ebc6c
- https://issuetracker.google.com/issues/40942152
- https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/devtools/devtools_ui_bindings.cc;l=1100;drc=de65c59454bb29fff1e642fb3528cd2c80e52fb4
- https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/webui/downloads/downloads_dom_handler.cc;l=244;drc=b37413daa8803e67405b635419ab665e0374a093
- https://source.chromium.org/chromium/chromium/src/+/main:content/browser/web_contents/web_contents_impl.h;l=2380;drc=ebb421b7cdc02be3ee4abf49d6bad7646b3da9ab
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/devtools-frontend/src/front_end/core/host/InspectorFrontendHost.ts;l=190;drc=4ab8cec6e9a5640f553f44afeec821b9e7050eb9
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/devtools-frontend/src/front_end/core/sdk/Connections.ts;l=292;drc=5efc7e9be253ceb20ebc8fcc1710f42623272bf7
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/devtools-frontend/src/front_end/panels/network/NetworkDataGridNode.ts;l=1069;drc=ebb421b7cdc02be3ee4abf49d6bad7646b3da9ab
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/devtools-frontend/src/front_end/panels/network/NetworkDataGridNode.ts;l=1085;drc=ebb421b7cdc02be3ee4abf49d6bad7646b3da9ab
- https://source.chromium.org/chromium/chromium/src/+/main:third_party/devtools-frontend/src/front_end/ui/legacy/components/utils/Linkifier.ts;l=533;drc=aec1575a78abeec098d606c3c738215ca874b3b4