CVE-2026-7935
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
TEST_Fcontent/browser/speech/tts_controller_unittest.cc |
modified |
Files Changed
content/browser/speech/tts_controller_impl.cccontent/browser/speech/tts_controller_impl.hcontent/browser/speech/tts_controller_unittest.cc
Patch
From 0793f4fdce65f5900c343dea6b2f4f33c3ef4b5d Mon Sep 17 00:00:00 2001 From: Evan Liu <[email protected]> Date: Tue, 31 Mar 2026 12:39:40 -0700 Subject: [PATCH] Fix Web Speech API audio persisting across page navigations Currently, speechSynthesis audio can continue playing after a page unloads or redirects to another origin. This CL fixes the issue by canceling the active TtsUtterance in the browser process when the WebContents' primary page changes. Fixed: 489624550 Change-Id: I385ffc9856c572576a27e3b95be807b66bc3f8a5 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7705458 Reviewed-by: Katie D <[email protected]> Commit-Queue: Evan Liu <[email protected]> Cr-Commit-Position: refs/heads/main@{#1608024} --- diff --git a/content/browser/speech/tts_controller_impl.cc b/content/browser/speech/tts_controller_impl.cc index b15ac71f..5a345f7e6 100644 --- a/content/browser/speech/tts_controller_impl.cc +++ b/content/browser/speech/tts_controller_impl.cc @@ -1011,6 +1011,10 @@ StopCurrentUtteranceAndRemoveUtterancesMatching(web_contents()); } +void TtsControllerImpl::PrimaryPageChanged(Page& page) { + StopCurrentUtteranceAndRemoveUtterancesMatching(web_contents()); +} + void TtsControllerImpl::OnVisibilityChanged(Visibility visibility) { if (visibility == Visibility::HIDDEN && stop_speaking_when_hidden_) StopCurrentUtteranceAndRemoveUtterancesMatching(web_contents()); diff --git a/content/browser/speech/tts_controller_impl.h b/content/browser/speech/tts_controller_impl.h index 4eb535d..ae67e2a8 100644 --- a/content/browser/speech/tts_controller_impl.h +++ b/content/browser/speech/tts_controller_impl.h @@ -195,6 +195,7 @@ // WebContentsObserver methods void WebContentsDestroyed() override; + void PrimaryPageChanged(Page& page) override; void OnVisibilityChanged(Visibility visibility) override; // net::NetworkChangeNotifier::NetworkChangeObserver diff --git a/content/browser/speech/tts_controller_unittest.cc b/content/browser/speech/tts_controller_unittest.cc index ebacbfb..5b7d4eef 100644 --- a/content/browser/speech/tts_controller_unittest.cc +++ b/content/browser/speech/tts_controller_unittest.cc @@ -625,6 +625,21 @@ EXPECT_FALSE(TtsControllerCurrentUtterance()); } +TEST_F(TtsControllerTest, StopsWhenWebContentsPrimaryPageChanged) { + std::unique_ptr<TestWebContents> web_contents = CreateWebContents(); + std::unique_ptr<TtsUtteranceImpl> utterance = + CreateUtteranceImpl(web_contents.get()); + + controller()->SpeakOrEnqueue(std::move(utterance)); + EXPECT_TRUE(controller()->IsSpeaking()); + EXPECT_TRUE(TtsControllerCurrentUtterance()); + + web_contents->NavigateAndCommit(GURL("https://example.com")); + // Navigating to a new page should reset + // |TtsController::current_utterance_|. + EXPECT_FALSE(TtsControllerCurrentUtterance()); +} + TEST_F(TtsControllerTest, StartsQueuedUtteranceWhenWebContentsDestroyed) { std::unique_ptr<WebContents> web_contents1 = CreateWebContents(); std::unique_ptr<WebContents> web_contents2 = CreateWebContents();
Regression Test / PoC
diff --git a/content/browser/speech/tts_controller_unittest.cc b/content/browser/speech/tts_controller_unittest.cc
index ebacbfb..5b7d4eef 100644
--- a/content/browser/speech/tts_controller_unittest.cc
+++ b/content/browser/speech/tts_controller_unittest.cc
@@ -625,6 +625,21 @@
EXPECT_FALSE(TtsControllerCurrentUtterance());
}
+TEST_F(TtsControllerTest, StopsWhenWebContentsPrimaryPageChanged) {
+ std::unique_ptr<TestWebContents> web_contents = CreateWebContents();
+ std::unique_ptr<TtsUtteranceImpl> utterance =
+ CreateUtteranceImpl(web_contents.get());
+
+ controller()->SpeakOrEnqueue(std::move(utterance));
+ EXPECT_TRUE(controller()->IsSpeaking());
+ EXPECT_TRUE(TtsControllerCurrentUtterance());
+
+ web_contents->NavigateAndCommit(GURL("https://example.com"));
+ // Navigating to a new page should reset
+ // |TtsController::current_utterance_|.
+ EXPECT_FALSE(TtsControllerCurrentUtterance());
+}
+
TEST_F(TtsControllerTest, StartsQueuedUtteranceWhenWebContentsDestroyed) {
std::unique_ptr<WebContents> web_contents1 = CreateWebContents();
std::unique_ptr<WebContents> web_contents2 = CreateWebContents();
Original Bug Report
SpeechSynthesis audio can appear to originate from another domain after fast redirect (UI/Audio Spoofing – may trick users / tricky victim)
Report description
SpeechSynthesis audio can appear to originate from another domain after fast redirect (UI/Audio Spoofing – may trick users / tricky victim)
Bug location
Where do you want to report your vulnerability?
Chrome VRP – Report security issues affecting the Chrome browser. See program rules
Which URL (or repository) have you found the vulnerability in?
https://cnfdnfial-ops.github.io/spoof/poc.html
The problem
Please describe the technical details of the vulnerability
A vulnerability has been identified in Chromium-based browsers where audio generated via the Web Speech API (speechSynthesis) can persist after a page navigation or redirect. According to the specification, speechSynthesis is document-bound and all utterances should terminate when the page is unloaded. In this case, a PoC demonstrates that speech audio can continue to play on the target page (e.g., https://google.com) after redirecting from the originating page.
Steps to Reproduce:
- Open a test HTML page containing a button that triggers
speechSynthesis.speak(). - Immediately after invoking
speechSynthesis.speak(), redirect to another page usingwindow.location.href. - Observe that the speech continues playing on the target page.
PoC Example:
<button onclick="
const utter = new SpeechSynthesisUtterance('This is a test message.');
speechSynthesis.speak(utter);
setTimeout(() => { window.location.href='https://google.com'; }, 1000);
">Test</button>
Expected Behavior: All speech utterances should terminate immediately when the page is unloaded or navigated away. No audio should persist on the destination page.
Actual Behavior: Speech audio continues playing on the destination page after the redirect, effectively bypassing page boundaries.
Impact / Security Implications:
- Cross-Origin Audio Injection: Audio from one origin can play on a different origin without user consent.
- Social Engineering / Phishing Potential: A malicious page could redirect a user to a trusted site and continue playing audio messages, potentially misleading users.
- User Experience / Privacy Risk: Unexpected audio from unrelated origins can confuse or alarm users, violating trust expectations.
Root Cause:
Chromium currently does not properly terminate active speechSynthesis utterances when a page unloads or navigates away. The audio context from the original page leaks into the new page context.
Recommended Mitigation:
Ensure all active speechSynthesis utterances are canceled during page unload or navigation events (beforeunload or unload) to enforce strict page-bound behavior.
Impact analysis
Impact and Potential Impact
Immediate Impact:
- Audio from the originating page continues to play on the destination page after navigation, violating the expected document-bound behavior of the Web Speech API (
speechSynthesis). - Users may hear messages originating from a different site without their consent, leading to confusion or disruption of the intended user experience.
Potential Security and Privacy Implications:
-
Cross-Origin Audio Injection:
- Malicious sites could use this behavior to play audio on trusted or high-profile domains (e.g.,
google.com) without permission. - This represents a potential vector for cross-origin abuse of audio output.
- Malicious sites could use this behavior to play audio on trusted or high-profile domains (e.g.,
-
Phishing and Social Engineering:
- Attackers could redirect users from a malicious site to a legitimate site and continue playing misleading messages.
- Users might perceive the audio as originating from the trusted site, increasing susceptibility to phishing or deceptive instructions.
-
User Experience and Trust Risks:
- Unexpected or unauthorized audio on high-profile sites can erode user trust.
- This can also cause accessibility or usability issues, especially if users rely on predictable audio feedback.
-
Spec Compliance Issue:
- The Web Speech API specification dictates that speech utterances must terminate when a page unloads.
- Allowing audio to persist across navigations represents a violation of expected standards, which could affect other browsers and future web platform implementations.
Severity Consideration:
- While not a direct code-execution vulnerability, the combination of cross-origin audio leakage and potential social engineering makes this a high-impact UX/security issue, especially for high-trust domains.
The cause
What version of Chrome have you found the security issue in?
Version 145.0.7632.160 (Official Build) (64-bit)
Is the security issue related to a crash?
No, it is not related to a crash.
Choose the type of vulnerability
Mixed content
How would you like to be publicly acknowledged for your report?
Qadhafy Muhammad Tera