CVE-2026-11097
Overview
Files Changed
android_webview/java/src/org/chromium/android_webview/WebAddressParser.javaandroid_webview/junit/src/org/chromium/android_webview/robolectric/WebAddressParserTest.java
Patch
From fdcc97cf602f7696b732e9336674a72a157fe96d Mon Sep 17 00:00:00 2001
From: Torne (Richard Coles) <torne@google.com>
Date: Mon, 04 May 2026 13:13:19 -0700
Subject: [PATCH] webview: handle empty password in WebAddressParser.
Fix the legacy URL fixup code in WebAddressParser (only used for setting
cookies via CookieManager) to correctly handle URLs that have an empty
password segment in the userinfo.
Bug: 500311718
Change-Id: I6667479a9b80c8e40856e720c7b108ad4de53476
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7810325
Reviewed-by: Nate Fischer <ntfschr@chromium.org>
Auto-Submit: Richard Coles <torne@chromium.org>
Commit-Queue: Nate Fischer <ntfschr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1624892}
---
diff --git a/android_webview/java/src/org/chromium/android_webview/WebAddressParser.java b/android_webview/java/src/org/chromium/android_webview/WebAddressParser.java
index 83228d9..b53c87bb 100644
--- a/android_webview/java/src/org/chromium/android_webview/WebAddressParser.java
+++ b/android_webview/java/src/org/chromium/android_webview/WebAddressParser.java
@@ -4,8 +4,6 @@
package org.chromium.android_webview;
-import androidx.annotation.NonNull;
-
import org.chromium.build.annotations.NullMarked;
import java.net.URISyntaxException;
@@ -41,9 +39,10 @@
// See android.util.Patterns.GOOD_IRI_CHAR.
private static final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
private static final String SCHEME = "(?:(http|https|file)\\:\\/\\/)?";
- // We replace the regex of AUTHORITY to fix crbug.com/1247395, this is the only functional
- // change in this file comparing to the original WebAddress from Android framework.
- private static final String AUTHORITY = "(?:([^/?#:]+(?::[^/?#]+)?)@)?";
+ // We replace the regex of AUTHORITY to fix crbug.com/1247395 and crbug.com/500311718, this is
+ // the only functional change in this file comparing to the original WebAddress from Android
+ // framework.
+ private static final String AUTHORITY = "(?:([^/?#:]+(?::[^/?#]*)?)@)?";
private static final String HOST =
"([" + GOOD_IRI_CHAR + "%_-][" + GOOD_IRI_CHAR + "%_\\.-]*|\\[[0-9a-fA-F:\\.]+\\])?";
private static final String PORT = "(?:\\:([0-9]*))?";
@@ -115,7 +114,6 @@
if (mScheme.equals("")) mScheme = "http";
}
- @NonNull
@Override
public String toString() {
String port = "";
diff --git a/android_webview/junit/src/org/chromium/android_webview/robolectric/WebAddressParserTest.java b/android_webview/junit/src/org/chromium/android_webview/robolectric/WebAddressParserTest.java
index 07949c8d..5e54c91 100644
--- a/android_webview/junit/src/org/chromium/android_webview/robolectric/WebAddressParserTest.java
+++ b/android_webview/junit/src/org/chromium/android_webview/robolectric/WebAddressParserTest.java
@@ -82,6 +82,11 @@
Assert.assertEquals("http://google.com./b/c/g", fixupUrl("http://google.com./b/c/g"));
Assert.assertEquals(
"http://www.myspace.com/?si=1", fixupUrl("http://www.myspace.com?si=1"));
+
+ // crbug.com/500311718
+ Assert.assertEquals(
+ "http://foo.com:@example.com/", fixupUrl("http://foo.com:@example.com/"));
+ Assert.assertEquals("http://foo.com:@example.com/", fixupUrl("foo.com:@example.com/"));
}
@Test
Original Bug Report
Potential WebAddressParser host confusion allows cross-origin cookie theft
Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports without the security team.
Overview: A parser differential exists in Android WebView’s WebAddressParser due to an incorrect regex handling URLs with empty passwords. This flaw incorrectly transforms URLs like ‘https://victim.com:@evil.com/' into ‘https://victim.com/@evil.com/'. Attackers can exploit this parser differential in applications with WebView cookie bridges to bypass validation and steal cross-origin cookies.
Affected files:
android_webview/java/src/org/chromium/android_webview/WebAddressParser.javaandroid_webview/glue/java/src/com/android/webview/chromium/CookieManagerAdapter.java
Estimated timestamp from git blame: 2021-09-10
Summary
A potential vulnerability exists in WebAddressParser.java within Android WebView due to an incorrect regular expression used to parse the authority component of a URL. This flaw creates a parser differential that can allow an attacker to bypass application-level host validations and access cross-origin cookies via the CookieManager API.
Technical Details
In WebAddressParser.java, the AUTHORITY regex is defined as:
private static final String AUTHORITY = "(?:([^/?#:]+(?::[^/?#]+)?)@)?";
When parsing a URL with an empty password (e.g., https://victim.com:@evil.com/), the AUTHORITY regex fails to match. The inner password sub-pattern (?::[^/?#]+)? greedily consumes the :@evil.com portion because the character class [^/?#] does not exclude the @ symbol. Consequently, the mandatory trailing @ for the outer AUTHORITY group cannot be satisfied, causing the entire group match to fail and be skipped.
Because AUTHORITY fails, the parser falls back to evaluating the remaining URL components:
- HOST: Matches
victim.com(stopping at the invalid:character). - PORT: Matches the
:but captures an empty string, effectively dropping the colon. - PATH: Matches the remainder, becoming
/@evil.com/.
The toString() method then reconstructs the URL as https://victim.com/@evil.com/.
This transformation is a significant security risk. Standard parsers like java.net.URL identify the host of the original payload (https://victim.com:@evil.com/) as evil.com. However, the native Chromium CookieManager uses GURL, which interprets the transformed URL (https://victim.com/@evil.com/) as having the host victim.com.
Potential Attacker Steps
Note: These are suggested steps to trigger the vulnerability, as our automated tooling cannot execute proof-of-concept code yet.
- An Android application implements a JavaScript bridge to allow WebView content to interact with the
CookieManager(e.g., to get/set cookies) to support its web functionality. - To secure this bridge, the application validates the requested URL using
java.net.URL(url).getHost()and ensures the host is in an allowlist of trusted domains. - An attacker navigates the user to a malicious page (
evil.com, assuming it is allowlisted or the attacker controls the starting domain) within the WebView. - The malicious page calls the exposed bridge with the payload
https://victim.com:@evil.com/. - The application’s validation succeeds because
java.net.URLcorrectly parses the host asevil.com. - The application passes the raw payload to
CookieManager.getCookie(url). - The WebView glue layer’s
CookieManagerAdapter.fixupUrl()processes the payload usingWebAddressParser, silently transforming it tohttps://victim.com/@evil.com/. - The native
AwCookieManagerqueriesvictim.comcookies and returns them, allowing the attacker to steal cross-origin session cookies.
Suggested Fix
The most robust fix is to deprecate and remove the custom regex-based WebAddressParser entirely, replacing it with Chromium’s native GURL parser via JNI or a standard robust Java parser.
If a quick regex fix is required, modify the password sub-pattern to explicitly exclude the @ symbol:
private static final String AUTHORITY = "(?:([^/?#:]+(?::[^/?#@]+)?)@)?";
This prevents the password group from greedily consuming the host portion when an empty password is provided.
Evaluated with Chrome root at commit: f200f57a19490707ff8bc7aa5de3cbc443a3afad
Results 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.