commit 976e9d6b7765a48f0a75513f45c5e73c4d99fc49
parent b7e1499bbcf76678201f41b969d5cc081201141d
Author: Maile Lucks <maile.lucks@gmail.com>
Date: Thu, 30 Oct 2025 19:38:11 +0000
Bug 1991887 - Add MOZILLA_PKIX_ERROR_INSUFFICIENT_CERTIFICATE_TRANSPARENCY to net-error-card component - r=jaws,fluent-reviewers,bolsson
Differential Revision: https://phabricator.services.mozilla.com/D268962
Diffstat:
3 files changed, 126 insertions(+), 1 deletion(-)
diff --git a/browser/base/content/test/about/browser_aboutCertError.js b/browser/base/content/test/about/browser_aboutCertError.js
@@ -107,7 +107,7 @@ add_task(async function checkReturnToAboutHome() {
BrowserTestUtils.removeTab(gBrowser.selectedTab);
}
- SpecialPowers.popPrefEnv();
+ await SpecialPowers.popPrefEnv();
}
});
@@ -699,6 +699,100 @@ add_task(async function testCertificateTransparency() {
// debug builds.
}).skip(!AppConstants.DEBUG);
+add_task(async function testCertificateTransparency_feltPrivacyTrue() {
+ info(
+ "Test that when certificate transparency is enforced, the right error page is shown."
+ );
+ // Enforce certificate transparency for certificates issued by our test root.
+ // This is only possible in debug builds, hence skipping this test in
+ // non-debug builds (see below).
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["security.pki.certificate_transparency.mode", 2],
+ [
+ "security.test.built_in_root_hash",
+ "8D:9D:57:09:E5:7D:D5:C6:4B:BE:24:70:E9:E5:BF:FF:16:F6:F2:C2:49:4E:0F:B9:37:1C:DD:3A:0E:10:45:F4",
+ ],
+ ["security.certerrors.felt-privacy-v1", true],
+ ],
+ });
+
+ for (let useFrame of [false, true]) {
+ const tab = await openErrorPage(GOOD_PAGE, useFrame);
+ const browser = tab.linkedBrowser;
+
+ let bc = browser.browsingContext;
+ if (useFrame) {
+ bc = bc.children[0];
+ }
+
+ const message = await SpecialPowers.spawn(bc, [], async function () {
+ const doc = content.document;
+
+ const netErrorCard = doc.querySelector("net-error-card").wrappedJSObject;
+ await netErrorCard.getUpdateComplete();
+
+ netErrorCard.advancedButton.scrollIntoView();
+ EventUtils.synthesizeMouseAtCenter(
+ netErrorCard.advancedButton,
+ {},
+ content
+ );
+
+ await ContentTaskUtils.waitForCondition(() => {
+ return (
+ netErrorCard.whyDangerous &&
+ netErrorCard.whyDangerous.textContent != ""
+ );
+ }, "Waiting for why dangerous text");
+ const args = JSON.parse(netErrorCard.whyDangerous.dataset.l10nArgs);
+ Assert.strictEqual(
+ args.hostname,
+ "example.com",
+ "Should list hostname in error message."
+ );
+
+ // Wait until fluent sets the errorCode inner text.
+ await ContentTaskUtils.waitForCondition(() => {
+ return (
+ netErrorCard.errorCode && netErrorCard.errorCode.textContent != ""
+ );
+ }, "error code has been set inside the advanced button panel");
+
+ netErrorCard.errorCode.scrollIntoView();
+ EventUtils.synthesizeMouseAtCenter(netErrorCard.errorCode, {}, content);
+ await ContentTaskUtils.waitForCondition(() => {
+ return (
+ netErrorCard.certErrorText &&
+ netErrorCard.certErrorText.textContent != ""
+ );
+ }, "Certificate Error is showing");
+
+ return {
+ certText: netErrorCard.certErrorText.textContent,
+ errorCode: netErrorCard.errorCode.textContent,
+ tagName: netErrorCard.errorCode.tagName.toLowerCase(),
+ };
+ });
+
+ Assert.ok(
+ message.errorCode.includes(
+ "MOZILLA_PKIX_ERROR_INSUFFICIENT_CERTIFICATE_TRANSPARENCY"
+ ),
+ "Correct error message found"
+ );
+ Assert.strictEqual(message.tagName, "a", "Error message is a link");
+ Assert.ok(message.certText.includes(GOOD_PAGE), "Correct URL found");
+
+ BrowserTestUtils.removeTab(gBrowser.selectedTab);
+ }
+
+ await SpecialPowers.popPrefEnv();
+
+ // Certificate transparency can only be enforced for our test certificates in
+ // debug builds.
+}).skip(!AppConstants.DEBUG);
+
/**
* A reusable helper that runs assertions on a network error page.
* It encapsulates the SpecialPowers.spawn call to be CSP-compliant.
diff --git a/toolkit/content/net-error-card.mjs b/toolkit/content/net-error-card.mjs
@@ -44,6 +44,7 @@ export class NetErrorCard extends MozLitElement {
returnButton: "#returnButton",
learnMoreLink: "#learnMoreLink",
whatCanYouDo: "#whatCanYouDo",
+ whyDangerous: "#fp-why-site-dangerous",
};
static ERROR_CODES = new Set([
@@ -53,6 +54,7 @@ export class NetErrorCard extends MozLitElement {
"SEC_ERROR_EXPIRED_CERTIFICATE",
"SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE",
"SSL_ERROR_NO_CYPHER_OVERLAP",
+ "MOZILLA_PKIX_ERROR_INSUFFICIENT_CERTIFICATE_TRANSPARENCY",
]);
constructor() {
@@ -154,6 +156,11 @@ export class NetErrorCard extends MozLitElement {
data-l10n-id="fp-neterror-connection-intro"
data-l10n-args='{"hostname": "${this.hostname}"}'
></p>`;
+ case "MOZILLA_PKIX_ERROR_INSUFFICIENT_CERTIFICATE_TRANSPARENCY":
+ return html`<p
+ data-l10n-id="fp-certerror-transparency-intro"
+ data-l10n-args='{"hostname": "${this.hostname}"}'
+ ></p>`;
}
return null;
@@ -282,6 +289,20 @@ export class NetErrorCard extends MozLitElement {
});
break;
}
+ case "MOZILLA_PKIX_ERROR_INSUFFICIENT_CERTIFICATE_TRANSPARENCY": {
+ content = this.advancedSectionTemplate({
+ whyDangerousL10nId: "fp-certerror-transparency-why-dangerous-body",
+ whyDangerousL10nArgs: {
+ hostname: this.hostname,
+ },
+ whatCanYouDoL10nId: "fp-certerror-transparency-what-can-you-do-body",
+ learnMoreL10nId: "fp-learn-more-about-secure-connection-failures",
+ learnMoreSupportPage: "connection-not-secure",
+ viewCert: true,
+ proceedButton: true,
+ });
+ break;
+ }
}
return html`<div class="advanced-container">
@@ -310,6 +331,7 @@ export class NetErrorCard extends MozLitElement {
data-l10n-id="fp-certerror-why-site-dangerous"
></strong>
<span
+ id="fp-why-site-dangerous"
data-l10n-id=${whyDangerousL10nId}
data-l10n-args=${JSON.stringify(whyDangerousL10nArgs)}
></span>`
diff --git a/toolkit/locales/en-US/toolkit/neterror/certError.ftl b/toolkit/locales/en-US/toolkit/neterror/certError.ftl
@@ -173,6 +173,7 @@ fp-certerror-hide-advanced-button = Hide advanced
fp-certerror-override-exception-button = Proceed to { $hostname } (Risky)
fp-certerror-intro = { -brand-short-name } spotted a potentially serious security issue with <strong>{ $hostname }</strong>. Someone pretending to be the site could try to steal things like credit card info, passwords, or emails.
fp-certerror-expired-into = { -brand-short-name } spotted a security issue with <strong>{ $hostname }</strong>. Either the site isn’t set up right or your device’s clock is set to the wrong date/time.
+fp-certerror-transparency-intro = Someone pretending to be <strong>{ $hostname }</strong> could try to steal things like credit card info, passwords, or emails.
##
@@ -221,6 +222,14 @@ fp-cert-error-code = Error Code: { $error }
# $datetime (Date) - Current datetime.
fp-datetime = { DATETIME($datetime, month: "short", year: "numeric", day: "numeric") } { DATETIME($datetime, timeStyle: "long") }
+# This string appears after the following string: "What makes the site look dangerous?" (fp-certerror-why-site-dangerous)
+# Variables:
+# $hostname (String) - Hostname of the website to which the user was trying to connect.
+fp-certerror-transparency-why-dangerous-body = { -brand-short-name } doesn’t trust { $hostname } because it couldn’t prove it meets public certificate transparency requirements.
+# This string appears after the following string: "What can you do about it?" (fp-certerror-what-can-you-do)
+fp-certerror-transparency-what-can-you-do-body = Probably nothing, since it’s likely there’s a problem with the site itself.
+
+
fp-learn-more-about-secure-connection-failures = Learn more about secure connection failures
fp-learn-more-about-cert-issues = Learn more about these kinds of certificate issues
fp-learn-more-about-time-related-errors = Learn more about troubleshooting time-related errors