Chrome · Voice
CVE-2026-113164
Memory Corruption in Voice
Overview
Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifchrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java |
modified |
Files Changed
chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.javachrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerBrowserTest.java
Patch
From f2e24c37ecb1148590bbec98d98a11b483d77f5d Mon Sep 17 00:00:00 2001
From: Sky Malice <skym@chromium.org>
Date: Fri, 18 Sep 2026 10:56:21 -0700
Subject: [PATCH] Validate voice search and share intent result URLs
Ensure URLs derived from voice search results and share intent extras
are validated via isUrlUnsafe() before returning them. When candidate
URLs from intent extras or AutocompleteCoordinator classification fail
validation, fall back to generating a search query URL using the default
search engine template.
TAG=agy
CONV=92dacbf6-8488-4ddc-8241-e41babdc8a4c
Bug: 500497398
Change-Id: I395567db24acd0f4ec484b757ef9f5246b286c4e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8421858
Reviewed-by: Tomasz Wiszkowski <ender@google.com>
Commit-Queue: Sky Malice <skym@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1700953}
---
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 632a1e37..54e78075 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -836,18 +836,23 @@
AutocompleteMatch match = AutocompleteCoordinator.classify(profile, query);
assert match != null;
- if (!match.isSearchSuggestion()) return match.getUrl().getSpec();
+ if (!match.isSearchSuggestion()
+ && !ExternalIntentUrlChecker.isUnsafeExternalIntentUrl(match.getUrl())) {
+ return match.getUrl().getSpec();
+ }
List<String> urls =
IntentUtils.safeGetStringArrayListExtra(
intent, RecognizerResultsIntent.EXTRA_VOICE_SEARCH_RESULT_URLS);
- if (urls != null && urls.size() > 0) {
- return urls.get(0);
- } else {
- return TemplateUrlServiceFactory.getForProfile(profile)
- .getUrlForVoiceSearchQuery(query)
- .getSpec();
+ if (urls != null && !urls.isEmpty()) {
+ String url = urls.get(0);
+ if (!TextUtils.isEmpty(url) && !isUrlUnsafe(url)) {
+ return url;
+ }
}
+ return TemplateUrlServiceFactory.getForProfile(profile)
+ .getUrlForVoiceSearchQuery(query)
+ .getSpec();
}
/**
@@ -1381,7 +1386,7 @@
Profile profile = ProfileManager.getLastUsedRegularProfile();
AutocompleteMatch match = AutocompleteCoordinator.classify(profile, text);
- if (match != null) {
+ if (match != null && !ExternalIntentUrlChecker.isUnsafeExternalIntentUrl(match.getUrl())) {
urls.add(match.getUrl().getSpec());
return urls;
}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerBrowserTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerBrowserTest.java
index ef68a07b..b5c42772 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerBrowserTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerBrowserTest.java
@@ -22,6 +22,7 @@
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.Batch;
import org.chromium.base.test.util.Feature;
+import org.chromium.components.embedder_support.util.UrlConstants;
import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
import org.chromium.url.JUnitTestGURLs;
@@ -84,6 +85,43 @@
@Test
@MediumTest
@UiThreadTest
+ @Feature({"Android-AppBase"})
+ public void testGetQueryFromVoiceSearchResultIntent_internalResultUrl() {
+ Intent intent = new Intent(RecognizerResultsIntent.ACTION_VOICE_SEARCH_RESULTS);
+ intent.putStringArrayListExtra(
+ RecognizerResultsIntent.EXTRA_VOICE_SEARCH_RESULT_STRINGS,
+ new ArrayList<>(Collections.singletonList(VOICE_SEARCH_QUERY)));
+ intent.putStringArrayListExtra(
+ RecognizerResultsIntent.EXTRA_VOICE_SEARCH_RESULT_URLS,
+ new ArrayList<>(Collections.singletonList(UrlConstants.VERSION_URL)));
+ String url = IntentHandler.getUrlFromVoiceSearchResult(intent);
+ Assert.assertNotNull(url);
+ Assert.assertFalse(
+ "Supplied internal URL should not be used: " + url,
+ url.startsWith(UrlConstants.CHROME_SCHEME));
+ assertThat(url, startsWith(VOICE_SEARCH_QUERY_URL));
+ }
+
+ @Test
+ @MediumTest
+ @UiThreadTest
+ @Feature({"Android-AppBase"})
+ public void testGetQueryFromVoiceSearchResultIntent_internalUrlQuery() {
+ Intent intent = new Intent(RecognizerResultsIntent.ACTION_VOICE_SEARCH_RESULTS);
+ intent.putStringArrayListExtra(
+ RecognizerResultsIntent.EXTRA_VOICE_SEARCH_RESULT_STRINGS,
+ new ArrayList<>(Collections.singletonList(UrlConstants.VERSION_URL)));
+ String url = IntentHandler.getUrlFromVoiceSearchResult(intent);
+ Assert.assertNotNull(url);
+ Assert.assertFalse(
+ "Internal URL query should fall back to search: " + url,
+ url.startsWith(UrlConstants.CHROME_SCHEME));
+ assertThat(url, startsWith("https://www.google.com/search?q="));
+ }
+
+ @Test
+ @MediumTest
+ @UiThreadTest
public void testGetURLFromShareIntent_validURL() {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, JUnitTestGURLs.EXAMPLE_URL.getSpec());
@@ -106,6 +144,21 @@
@Test
@MediumTest
@UiThreadTest
+ public void testGetURLFromShareIntent_internalUrl() {
+ Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.putExtra(Intent.EXTRA_TEXT, UrlConstants.VERSION_URL);
+ intent.setType("text/plain");
+ String url = IntentHandler.getUrlFromShareIntent(intent);
+ Assert.assertNotNull(url);
+ Assert.assertFalse(
+ "Internal URL share should fall back to search: " + url,
+ url.startsWith(UrlConstants.CHROME_SCHEME));
+ assertThat(url, startsWith("https://www.google.com/search?q="));
+ }
+
+ @Test
+ @MediumTest
+ @UiThreadTest
public void testGetURLFromShareIntent_plainText() {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, "test");
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page