tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 4e6368b8e07f48339d6730e36c2be297e3bf1d6c
parent 2c0e59dd8de119516c14f0aa224da19bbad8dc84
Author: Jack Brown <jbrown@mozilla.com>
Date:   Wed, 10 Dec 2025 18:47:03 +0000

Bug 1992384 - Add MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE support to net-error-card - r=niklas,fluent-reviewers,bolsson

Differential Revision: https://phabricator.services.mozilla.com/D274174

Diffstat:
Mbrowser/base/content/test/about/browser.toml | 2++
Abrowser/base/content/test/about/browser_aboutCertError_notYetValid.js | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtoolkit/content/net-error-card.mjs | 21+++++++++++++++++++++
Mtoolkit/locales/en-US/toolkit/neterror/certError.ftl | 10++++++++++
4 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/browser/base/content/test/about/browser.toml b/browser/base/content/test/about/browser.toml @@ -32,6 +32,8 @@ support-files = [ ["browser_aboutCertError_noSubjectAltName.js"] +["browser_aboutCertError_notYetValid.js"] + ["browser_aboutCertError_offlineSupport.js"] ["browser_aboutCertError_offlineSupport_feltPrivacyV1.js"] diff --git a/browser/base/content/test/about/browser_aboutCertError_notYetValid.js b/browser/base/content/test/about/browser_aboutCertError_notYetValid.js @@ -0,0 +1,100 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const BAD_CERT_PAGE = "https://expired.example.com"; +const NOT_YET_VALID_CERT_PATH = + "../../../../../security/manager/ssl/tests/mochitest/browser/ca.pem"; + +function pemToBase64(pem) { + return pem + .replace(/-----BEGIN CERTIFICATE-----/, "") + .replace(/-----END CERTIFICATE-----/, "") + .replace(/\s+/g, ""); +} + +add_setup(async function () { + await SpecialPowers.pushPrefEnv({ + set: [ + ["test.wait300msAfterTabSwitch", true], + ["security.certerrors.felt-privacy-v1", true], + ], + }); +}); + +add_task(async function testNotYetValidCert() { + const pem = await IOUtils.readUTF8(getTestFilePath(NOT_YET_VALID_CERT_PATH)); + const certBase64 = pemToBase64(pem); + const tab = await openErrorPage(BAD_CERT_PAGE); + const browser = tab.linkedBrowser; + + await SpecialPowers.spawn(browser, [certBase64], async cert => { + const mockErrorInfo = { + errorCodeString: "MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE", + errorIsOverridable: false, + channelStatus: 0, + overridableErrorCategory: "expired-or-not-yet-valid", + validNotBefore: Date.now() + 1000 * 1000, + validNotAfter: Date.now() + 1000 * 2000, + certValidityRangeNotBefore: Date.now() + 1000 * 1000, + certValidityRangeNotAfter: Date.now() + 1000 * 2000, + issuerCommonName: "Test CA", + errorMessage: "The server presented a certificate that is not yet valid.", + hasHSTS: false, + hasHPKP: false, + certChainStrings: [cert], + }; + + content.document.getFailedCertSecurityInfo = () => mockErrorInfo; + + const netErrorCard = + content.document.querySelector("net-error-card").wrappedJSObject; + const info = Cu.cloneInto(mockErrorInfo, netErrorCard); + netErrorCard.errorInfo = info; + await netErrorCard.getUpdateComplete(); + + netErrorCard.advancedButton.scrollIntoView(); + EventUtils.synthesizeMouseAtCenter( + netErrorCard.advancedButton, + {}, + content + ); + + await ContentTaskUtils.waitForCondition( + () => ContentTaskUtils.isVisible(netErrorCard.advancedContainer), + "Advanced container is visible" + ); + + Assert.ok( + netErrorCard.advancedShowing, + "Advanced details are shown for not-yet-valid certificates." + ); + Assert.ok( + netErrorCard.exceptionButton, + "Proceed button should be shown for not-yet-valid certificates." + ); + Assert.equal( + netErrorCard.certErrorIntro.dataset.l10nId, + "fp-certerror-intro", + "Using the 'certificate error' intro." + ); + Assert.equal( + netErrorCard.whyDangerous.dataset.l10nId, + "fp-certerror-pkix-not-yet-valid-why-dangerous-body", + "Using the 'not yet valid' variant of the 'Why Dangerous' copy." + ); + Assert.equal( + netErrorCard.whatCanYouDo.dataset.l10nId, + "fp-certerror-pkix-not-yet-valid-what-can-you-do-body", + "Using the 'not yet valid' variant of the 'What can you do' copy." + ); + Assert.equal( + netErrorCard.learnMoreLink.getAttribute("support-page"), + "time-errors", + "'Learn more' link points to the time-related errors support page." + ); + }); + + await BrowserTestUtils.removeTab(tab); +}); diff --git a/toolkit/content/net-error-card.mjs b/toolkit/content/net-error-card.mjs @@ -72,6 +72,7 @@ export class NetErrorCard extends MozLitElement { "NS_ERROR_OFFLINE", "NS_ERROR_DOM_COOP_FAILED", "NS_ERROR_DOM_COEP_FAILED", + "MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE", ]); static isSupported() { @@ -224,6 +225,7 @@ export class NetErrorCard extends MozLitElement { case "SSL_ERROR_BAD_CERT_DOMAIN": case "SEC_ERROR_EXPIRED_CERTIFICATE": case "MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT": + case "MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE": return html`<p id="certErrorIntro" data-l10n-id="fp-certerror-intro" @@ -399,6 +401,25 @@ export class NetErrorCard extends MozLitElement { }); break; } + case "MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE": { + const notBefore = this.errorInfo.validNotBefore; + content = this.advancedSectionTemplate({ + whyDangerousL10nId: + "fp-certerror-pkix-not-yet-valid-why-dangerous-body", + whyDangerousL10nArgs: { + date: notBefore, + }, + whatCanYouDoL10nId: + "fp-certerror-pkix-not-yet-valid-what-can-you-do-body", + whatCanYouDoL10nArgs: { + date: Date.now(), + }, + learnMoreL10nId: "fp-learn-more-about-time-related-errors", + learnMoreSupportPage: "time-errors", + viewCert: true, + }); + break; + } } return html`<div class="advanced-container"> diff --git a/toolkit/locales/en-US/toolkit/neterror/certError.ftl b/toolkit/locales/en-US/toolkit/neterror/certError.ftl @@ -240,3 +240,13 @@ fp-certerror-transparency-what-can-you-do-body = Probably nothing, since it’s 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 + +# This string appears after the following string: "What makes the site look dangerous?" (fp-certerror-why-site-dangerous) +# Variables: +# $datetime (Date) - Date the cert becomes valid. +fp-certerror-pkix-not-yet-valid-why-dangerous-body = { -brand-short-name } doesn’t trust this site because it looks like the certificate provided isn’t valid until { DATETIME($date, timeStyle: "short") } on { DATETIME($date, month: "numeric", day: "numeric", year: "numeric") }. + +# This string appears after the following string: "What can you do about it?" (fp-certerror-what-can-you-do) +# Variables: +# $date (Date) - Device's clock date. +fp-certerror-pkix-not-yet-valid-what-can-you-do-body = Your device’s clock is set to { DATETIME($date, timeStyle: "short") } { DATETIME($date, month: "numeric", day: "numeric", year: "numeric") }. If this is correct, the security issue is probably with the site itself. If it’s wrong, you can change it in your device’s system settings.