CVE-2026-17939
Overview
Files Changed
chrome/browser/resources/password_manager/dialogs/delete_password_disclaimer_dialog.ts
Patch
From a14394693bbf27f99ccfd4bf28105bdd2dd04bab Mon Sep 17 00:00:00 2001
From: Andrii Natiahlyi <natiahlyi@google.com>
Date: Wed, 10 Jun 2026 06:20:33 -0700
Subject: [PATCH] Escape origin in delete password disclaimer dialog.
Fixed: 514060089
Change-Id: Ie32f0ff4e24e19d93856514da28d9f7e76bb3629
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7916933
Reviewed-by: Adem Derinel <derinel@google.com>
Commit-Queue: Andrii Natiahlyi <natiahlyi@google.com>
Cr-Commit-Position: refs/heads/main@{#1644596}
---
diff --git a/chrome/browser/resources/password_manager/dialogs/delete_password_disclaimer_dialog.ts b/chrome/browser/resources/password_manager/dialogs/delete_password_disclaimer_dialog.ts
index 39ba2f5..421e52b 100644
--- a/chrome/browser/resources/password_manager/dialogs/delete_password_disclaimer_dialog.ts
+++ b/chrome/browser/resources/password_manager/dialogs/delete_password_disclaimer_dialog.ts
@@ -9,6 +9,7 @@
import type {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
import type {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
+import {htmlEscape} from 'chrome://resources/js/util.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import type {PasswordManagerProxy} from '../password_manager_proxy.js';
@@ -85,10 +86,11 @@
return window.trustedTypes!.emptyHTML;
}
+ const escapedOrigin = htmlEscape(this.origin ?? '');
return this.i18nAdvanced('deletePasswordConfirmationDescription', {
substitutions: [
- this.origin,
- `<a href='${this.actionUrl}' target='_blank'>${this.origin}</a>`,
+ escapedOrigin,
+ `<a href='${this.actionUrl}' target='_blank'>${escapedOrigin}</a>`,
],
});
}
Original Bug Report
Potential HTML and Link Injection in chrome://password-manager via Affiliation Service Name
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. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.
Overview: A potential vulnerability in the Password Manager WebUI allows a compromised network process to inject arbitrary allow-listed HTML and privileged links into disclaimer dialogs. This is caused by the unsafe interpolation of network-supplied affiliation names into a sanitized HTML sink.
Affected files:
chrome/browser/resources/password_manager/dialogs/delete_password_disclaimer_dialog.tschrome/browser/resources/password_manager/dialogs/delete_password_disclaimer_dialog.htmlcomponents/affiliations/core/browser/lookup_affiliation_response_parser.cc
Estimated timestamp from git blame: Unknown (Google3 checkout)
Summary
A potential security vulnerability exists in the chrome://password-manager WebUI where unescaped, network-controlled affiliation names are injected into the DOM using inner-h-t-m-l. While the WebUI employs a HTML sanitizer (parseHtmlSubset), this sanitizer explicitly allows various formatting tags and <a> tags with chrome:// or https:// schemes. This allows an attacker who has compromised the network process to perform high-fidelity UI spoofing and link injection within a privileged WebUI context.
Root Cause Analysis
The issue stems from the implementation of getDescriptionHtml_() in chrome/browser/resources/password_manager/dialogs/delete_password_disclaimer_dialog.ts. The method takes this.origin (which can contain an affiliation name supplied by the network) and interpolates it into an HTML string that is subsequently passed to i18nAdvanced:
// chrome/browser/resources/password_manager/dialogs/delete_password_disclaimer_dialog.ts
private getDescriptionHtml_(): TrustedHTML {
// ...
return this.i18nAdvanced('deletePasswordConfirmationDescription', {
substitutions: [
this.origin, // $1: Raw network-supplied string
`<a href='${this.actionUrl}' target='_blank'>${this.origin}</a>`, // $2: HTML built with raw string
],
});
}
The i18nAdvanced function (in I18nMixin) uses loadTimeData.getStringF to perform positional substitution of the raw strings into the localized template. The resulting string is then passed to sanitizeInnerHtml, which utilizes parseHtmlSubset for validation.
parseHtmlSubset (in ui/webui/resources/js/parse_html_subset.ts) is designed to prevent script execution but explicitly allow-lists several tags (<a>, <b>, <i>, <div>, <span>, <p>, etc.) and allows <a> tags to have href attributes pointing to chrome:// or https:// URLs. Consequently, an attacker can inject tags like </a><b>Spoofed Content</b><a href='chrome://settings/reset'> to break out of the intended link and inject arbitrary content or malicious links.
Potential Trigger Path (Suggested)
- Network Response Modification: An attacker, having compromised the sandboxed network process, intercepts a response from the Affiliation Service (e.g., a
lookupByHashPrefixrequest). - Payload Injection: The attacker modifies the
group_branding_info.namefield in the response to include a malicious HTML payload (e.g.,</a><a href='chrome://settings/reset'>Reset Browser Settings). - Data Propagation: The Browser process parses this response and stores the malicious name in the Affiliation Database (SQLite). The data is eventually exposed to the Password Manager WebUI via the
chrome.passwordsPrivateAPI. - UI Interaction: A user navigates to
chrome://password-manager/checkupand chooses to delete a credential associated with the compromised affiliation. This triggers the display of thedelete-password-disclaimer-dialog. - Injection: The WebUI renders the dialog, processing the malicious
originstring through the vulnerablegetDescriptionHtml_path and injecting the attacker’s HTML into the DOM viainner-h-t-m-l.
Impact
An attacker can perform sophisticated UI spoofing within the privileged chrome://password-manager interface. This can be used to mislead users into performing sensitive actions (e.g., resetting browser settings or visiting phishing sites) while they believe they are interacting with a trusted Chrome dialog.
Suggested Fix
All substitutions passed to i18nAdvanced should be treated as plain text and escaped before interpolation. Alternatively, the WebUI should avoid using inner-h-t-m-l for strings that incorporate untrusted, network-supplied data.
Evaluated with Chrome root at commit: 1a8d40fc44df2088d5945c0bf53584038aa1614a
Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:
- If you are familiar with the severity guidelines, you may adjust the severity.
- If this is a false positive, and there’s no work to be done, please close as WAI.
- If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.
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.