From 76d43c994d08f5aa28657192ba4bbceb37f907cc Mon Sep 17 00:00:00 2001 From: Richard Pospesel Date: Fri, 8 Jun 2018 13:38:40 -0700 Subject: [PATCH] Bug 23247: Communicating security expectations for .onion Encrypting pages hosted on Onion Services with SSL/TLS is redundant (in terms of hiding content) as all traffic within the Tor network is already fully encrypted. Therefore, serving HTTP pages from an Onion Service is more or less fine. Prior to this patch, Tor Browser would mostly treat pages delivered via Onion Services as well as pages delivered in the ordinary fashion over the internet in the same way. This created some inconsistencies in behaviour and misinformation presented to the user relating to the security of pages delivered via Onion Services: - HTTP Onion Service pages did not have any 'lock' icon indicating the site was secure - HTTP Onion Service pages would be marked as unencrypted in the Page Info screen - Mixed-mode content restrictions did not apply to HTTP Onion Service pages embedding Non-Onion HTTP content This patch fixes the above issues, and also adds several new 'Onion' icons to the mix to indicate all of the various permutations of Onion Services hosted HTTP or HTTPS pages with HTTP or HTTPS content. Strings for Onion Service Page Info page are pulled from Torbutton's localization strings. --- browser/base/content/browser-siteIdentity.js | 73 +++++++++++-------- browser/base/content/pageinfo/security.js | 65 ++++++++++++++--- .../identity-block/identity-block.inc.css | 20 +++++ .../shared/identity-block/onion-slash.svg | 5 ++ .../shared/identity-block/onion-warning.svg | 6 ++ .../themes/shared/identity-block/onion.svg | 3 + browser/themes/shared/jar.inc.mn | 3 + docshell/base/nsDocShell.cpp | 4 +- dom/base/nsContentUtils.cpp | 19 +++++ dom/base/nsContentUtils.h | 5 ++ dom/base/nsGlobalWindowOuter.cpp | 3 +- dom/presentation/PresentationRequest.cpp | 3 +- dom/security/nsMixedContentBlocker.cpp | 31 ++++++-- .../manager/ssl/nsSecureBrowserUIImpl.cpp | 47 ++++++++---- 14 files changed, 222 insertions(+), 65 deletions(-) create mode 100644 browser/themes/shared/identity-block/onion-slash.svg create mode 100644 browser/themes/shared/identity-block/onion-warning.svg create mode 100644 browser/themes/shared/identity-block/onion.svg diff --git a/browser/base/content/browser-siteIdentity.js b/browser/base/content/browser-siteIdentity.js index 5d131720a4d56..4a660504666cd 100644 --- a/browser/base/content/browser-siteIdentity.js +++ b/browser/base/content/browser-siteIdentity.js @@ -113,6 +113,10 @@ var gIdentityHandler = { ); }, + get _uriIsOnionHost() { + return this._uriHasHost ? this._uri.host.toLowerCase().endsWith(".onion") : false; + }, + // smart getters get _identityPopup() { delete this._identityPopup; @@ -595,12 +599,12 @@ var gIdentityHandler = { get pointerlockFsWarningClassName() { // Note that the fullscreen warning does not handle _isSecureInternalUI. if (this._uriHasHost && this._isEV) { - return "verifiedIdentity"; + return this._uriIsOnionHost ? "onionVerifiedIdentity" : "verifiedIdentity"; } if (this._uriHasHost && this._isSecure) { - return "verifiedDomain"; + return this._uriIsOnionHost ? "onionVerifiedDomain" : "verifiedDomain"; } - return "unknownIdentity"; + return this._uriIsOnionHost ? "onionUnknownIdentity" : "unknownIdentity"; }, /** @@ -608,6 +612,10 @@ var gIdentityHandler = { * built-in (returns false) or imported (returns true). */ _hasCustomRoot() { + if (!this._secInfo) { + return false; + } + let issuerCert = null; // Walk the whole chain to get the last cert. // eslint-disable-next-line no-empty @@ -635,9 +643,10 @@ var gIdentityHandler = { let brandBundle = document.getElementById("bundle_brand"); icon_label = brandBundle.getString("brandShorterName"); } else if (this._uriHasHost && this._isEV) { - this._identityBox.className = "verifiedIdentity"; + let uriIsOnionHost = this._uriIsOnionHost; + this._identityBox.className = uriIsOnionHost ? "onionVerifiedIdentity" : "verifiedIdentity"; if (this._isMixedActiveContentBlocked) { - this._identityBox.classList.add("mixedActiveBlocked"); + this._identityBox.classList.add(uriIsOnionHost ? "onionMixedActiveBlocked" : "mixedActiveBlocked"); } if (!this._isCertUserOverridden) { @@ -671,10 +680,12 @@ var gIdentityHandler = { "identity.extension.label", [extensionName] ); - } else if (this._uriHasHost && this._isSecure) { - this._identityBox.className = "verifiedDomain"; + // _isSecure implicitly includes onion services, which may not have an SSL certificate + } else if (this._uriHasHost && this._isSecure && this._secInfo != null) { + const uriIsOnionHost = this._uriIsOnionHost; + this._identityBox.className = uriIsOnionHost ? "onionVerifiedDomain" : "verifiedDomain"; if (this._isMixedActiveContentBlocked) { - this._identityBox.classList.add("mixedActiveBlocked"); + this._identityBox.classList.add(uriIsOnionHost ? "onionMixedActiveBlocked" : "mixedActiveBlocked"); } if (!this._isCertUserOverridden) { // It's a normal cert, verifier is the CA Org. @@ -693,35 +704,38 @@ var gIdentityHandler = { // For net errors we should not show notSecure as it's likely confusing this._identityBox.className = "unknownIdentity"; } else { + const uriIsOnionHost = this._uriIsOnionHost; if (this._isBroken) { - this._identityBox.className = "unknownIdentity"; + this._identityBox.className = uriIsOnionHost ? "onionUnknownIdentity" : "unknownIdentity"; if (this._isMixedActiveContentLoaded) { - this._identityBox.classList.add("mixedActiveContent"); + this._identityBox.classList.add(uriIsOnionHost ? "onionMixedActiveContent" : "mixedActiveContent"); } else if (this._isMixedActiveContentBlocked) { - this._identityBox.classList.add( - "mixedDisplayContentLoadedActiveBlocked" - ); + this._identityBox.classList.add(uriIsOnionHost ? "onionMixedDisplayContentLoadedActiveBlocked" : "mixedDisplayContentLoadedActiveBlocked"); } else if (this._isMixedPassiveContentLoaded) { - this._identityBox.classList.add("mixedDisplayContent"); + this._identityBox.classList.add(uriIsOnionHost ? "onionMixedDisplayContent" : "mixedDisplayContent"); } else { + // TODO: ignore weak https cipher for onionsites? this._identityBox.classList.add("weakCipher"); } } else { - let warnOnInsecure = - this._insecureConnectionIconEnabled || - (this._insecureConnectionIconPBModeEnabled && - PrivateBrowsingUtils.isWindowPrivate(window)); - let className = warnOnInsecure ? "notSecure" : "unknownIdentity"; - this._identityBox.className = className; - - let warnTextOnInsecure = - this._insecureConnectionTextEnabled || - (this._insecureConnectionTextPBModeEnabled && - PrivateBrowsingUtils.isWindowPrivate(window)); - if (warnTextOnInsecure) { - icon_label = gNavigatorBundle.getString("identity.notSecure.label"); - this._identityBox.classList.add("notSecureText"); + if (!uriIsOnionHost) { + let warnOnInsecure = this._insecureConnectionIconEnabled || + (this._insecureConnectionIconPBModeEnabled && + PrivateBrowsingUtils.isWindowPrivate(window)); + let className = warnOnInsecure ? "notSecure" : "unknownIdentity"; + this._identityBox.className = className; + + let warnTextOnInsecure = this._insecureConnectionTextEnabled || + (this._insecureConnectionTextPBModeEnabled && + PrivateBrowsingUtils.isWindowPrivate(window)); + if (warnTextOnInsecure) { + icon_label = gNavigatorBundle.getString("identity.notSecure.label"); + this._identityBox.classList.add("notSecureText"); + } + // http onion is secure + } else { + this._identityBox.className = "onionUnknownIdentity"; } } if (this._hasInsecureLoginForms) { @@ -732,7 +746,8 @@ var gIdentityHandler = { } if (this._isCertUserOverridden) { - this._identityBox.classList.add("certUserOverridden"); + const uriIsOnionHost = this._uriIsOnionHost; + this._identityBox.classList.add(uriIsOnionHost ? "onionCertUserOverridden" : "certUserOverridden"); // Cert is trusted because of a security exception, verifier is a special string. tooltip = gNavigatorBundle.getString( "identity.identified.verified_by_you" diff --git a/browser/base/content/pageinfo/security.js b/browser/base/content/pageinfo/security.js index e432c8a3911dc..a0336a67ee420 100644 --- a/browser/base/content/pageinfo/security.js +++ b/browser/base/content/pageinfo/security.js @@ -22,6 +22,13 @@ ChromeUtils.defineModuleGetter( "PluralForm", "resource://gre/modules/PluralForm.jsm" ); +XPCOMUtils.defineLazyGetter( + this, + "gTorButtonBundle", + function() { + return Services.strings.createBundle("chrome://torbutton/locale/torbutton.properties"); + } +); var security = { init(uri, windowInfo) { @@ -56,6 +63,10 @@ var security = { Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT); var isInsecure = ui.state & Ci.nsIWebProgressListener.STATE_IS_INSECURE; var isEV = ui.state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL; + var isOnion = false; + if (hostName && hostName.endsWith(".onion")) { + isOnion = true; + } var secInfo = ui.secInfo; if (!isInsecure && secInfo) { @@ -71,6 +82,7 @@ var security = { isBroken, isMixed, isEV, + isOnion, cert, certificateTransparency: undefined, }; @@ -130,6 +142,7 @@ var security = { isBroken, isMixed, isEV, + isOnion, cert: null, certificateTransparency: null, }; @@ -329,23 +342,53 @@ function securityOnLoad(uri, windowInfo) { } msg2 = pkiBundle.getString("pageInfo_Privacy_None2"); } else if (info.encryptionStrength > 0) { - hdr = pkiBundle.getFormattedString( - "pageInfo_EncryptionWithBitsAndProtocol", - [info.encryptionAlgorithm, info.encryptionStrength + "", info.version] - ); + if (!info.isOnion) { + hdr = pkiBundle.getFormattedString( + "pageInfo_EncryptionWithBitsAndProtocol", + [info.encryptionAlgorithm, info.encryptionStrength + "", info.version] + ); + } else { + try { + hdr = gTorButtonBundle.formatStringFromName( + "pageInfo_OnionEncryptionWithBitsAndProtocol", + [ + info.encryptionAlgorithm, + info.encryptionStrength + "", + info.version, + ], + 3 + ); + } catch(err) { + hdr = "Connection Encrypted (Onion Service, " + + info.encryptionAlgorithm + + ", " + + info.encryptionStrength + + " bit keys, " + + info.version + + ")"; + } + } msg1 = pkiBundle.getString("pageInfo_Privacy_Encrypted1"); msg2 = pkiBundle.getString("pageInfo_Privacy_Encrypted2"); security._cert = info.cert; } else { - hdr = pkiBundle.getString("pageInfo_NoEncryption"); - if (info.hostName != null) { - msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_None1", [ - info.hostName, - ]); + if (!info.isOnion) { + hdr = pkiBundle.getString("pageInfo_NoEncryption"); + if (info.hostName != null) + msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_None1", [info.hostName]); + else + msg1 = pkiBundle.getString("pageInfo_Privacy_None4"); + msg2 = pkiBundle.getString("pageInfo_Privacy_None2"); } else { - msg1 = pkiBundle.getString("pageInfo_Privacy_None4"); + try { + hdr = gTorButtonBundle.GetStringFromName("pageInfo_OnionEncryption"); + } catch (err) { + hdr = "Connection Encrypted (Onion Service)"; + } + + msg1 = pkiBundle.getString("pageInfo_Privacy_Encrypted1"); + msg2 = pkiBundle.getString("pageInfo_Privacy_Encrypted2"); } - msg2 = pkiBundle.getString("pageInfo_Privacy_None2"); } setText("security-technical-shortform", hdr); setText("security-technical-longform1", msg1); diff --git a/browser/themes/shared/identity-block/identity-block.inc.css b/browser/themes/shared/identity-block/identity-block.inc.css index ec8840fe063bf..64f25067a1cd3 100644 --- a/browser/themes/shared/identity-block/identity-block.inc.css +++ b/browser/themes/shared/identity-block/identity-block.inc.css @@ -295,6 +295,26 @@ toolbar[brighttext] #urlbar[pageproxystate="valid"] > #identity-box.chromeUI > # visibility: visible; } +#urlbar[pageproxystate="valid"] > #identity-box.onionUnknownIdentity > #connection-icon, +#urlbar[pageproxystate="valid"] > #identity-box.onionVerifiedDomain > #connection-icon, +#urlbar[pageproxystate="valid"] > #identity-box.onionVerifiedIdentity > #connection-icon, +#urlbar[pageproxystate="valid"] > #identity-box.onionMixedActiveBlocked > #connection-icon { + list-style-image: url(chrome://browser/skin/onion.svg); + visibility: visible; +} + +#urlbar[pageproxystate="valid"] > #identity-box.onionMixedDisplayContent > #connection-icon, +#urlbar[pageproxystate="valid"] > #identity-box.onionMixedDisplayContentLoadedActiveBlocked > #connection-icon, +#urlbar[pageproxystate="valid"] > #identity-box.onionCertUserOverridden > #connection-icon { + list-style-image: url(chrome://browser/skin/onion-warning.svg); + visibility: visible; +} + +#urlbar[pageproxystate="valid"] > #identity-box.onionMixedActiveContent > #connection-icon { + list-style-image: url(chrome://browser/skin/onion-slash.svg); + visibility: visible; +} + #identity-box.extensionPage > #extension-icon { list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric-16.svg); visibility: visible; diff --git a/browser/themes/shared/identity-block/onion-slash.svg b/browser/themes/shared/identity-block/onion-slash.svg new file mode 100644 index 0000000000000..e7c98b7694827 --- /dev/null +++ b/browser/themes/shared/identity-block/onion-slash.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/browser/themes/shared/identity-block/onion-warning.svg b/browser/themes/shared/identity-block/onion-warning.svg new file mode 100644 index 0000000000000..d42a7dab72465 --- /dev/null +++ b/browser/themes/shared/identity-block/onion-warning.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/browser/themes/shared/identity-block/onion.svg b/browser/themes/shared/identity-block/onion.svg new file mode 100644 index 0000000000000..b123a9786acca --- /dev/null +++ b/browser/themes/shared/identity-block/onion.svg @@ -0,0 +1,3 @@ + + + diff --git a/browser/themes/shared/jar.inc.mn b/browser/themes/shared/jar.inc.mn index 0e4bc99187249..ecdfd25aa7a31 100644 --- a/browser/themes/shared/jar.inc.mn +++ b/browser/themes/shared/jar.inc.mn @@ -58,6 +58,9 @@ skin/classic/browser/connection-secure.svg (../shared/identity-block/connection-secure.svg) skin/classic/browser/connection-mixed-passive-loaded.svg (../shared/identity-block/connection-mixed-passive-loaded.svg) skin/classic/browser/connection-mixed-active-loaded.svg (../shared/identity-block/connection-mixed-active-loaded.svg) + skin/classic/browser/onion.svg (../shared/identity-block/onion.svg) + skin/classic/browser/onion-slash.svg (../shared/identity-block/onion-slash.svg) + skin/classic/browser/onion-warning.svg (../shared/identity-block/onion-warning.svg) skin/classic/browser/identity-icon.svg (../shared/identity-block/identity-icon.svg) skin/classic/browser/identity-icon-notice.svg (../shared/identity-block/identity-icon-notice.svg) skin/classic/browser/info.svg (../shared/info.svg) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 5566ce3b435e9..4abdd088d4ffe 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -63,6 +63,7 @@ #include "mozilla/dom/ChildSHistory.h" #include "mozilla/dom/nsCSPContext.h" #include "mozilla/dom/LoadURIOptionsBinding.h" +#include "mozilla/dom/nsMixedContentBlocker.h" #include "mozilla/net/ReferrerPolicy.h" #include "mozilla/net/UrlClassifierFeatureFactory.h" @@ -5588,7 +5589,8 @@ nsDocShell::GetAllowMixedContentAndConnectionData( // aRootHasSecureConnection should be false. nsCOMPtr rootUri = rootPrincipal->GetURI(); if (nsContentUtils::IsSystemPrincipal(rootPrincipal) || !rootUri || - !SchemeIsHTTPS(rootUri)) { + (!SchemeIsHTTPS(rootUri) && + !nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(rootUri))) { *aRootHasSecureConnection = false; } diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 52ac6180a7282..fca667f9b9d43 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -9361,6 +9361,25 @@ bool nsContentUtils::HttpsStateIsModern(Document* aDocument) { return false; } +/* static */ bool nsContentUtils::DocumentHasOnionURI(Document* aDocument) { + if (!aDocument) { + return false; + } + + nsIURI* uri = aDocument->GetDocumentURI(); + if (!uri) { + return false; + } + + nsAutoCString host; + if (NS_SUCCEEDED(uri->GetHost(host))) { + bool hasOnionURI = StringEndsWith(host, NS_LITERAL_CSTRING(".onion")); + return hasOnionURI; + } + + return false; +} + /* static */ void nsContentUtils::TryToUpgradeElement(Element* aElement) { NodeInfo* nodeInfo = aElement->NodeInfo(); diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index a0261874212fb..0f8b860f9fbfa 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -3033,6 +3033,11 @@ class nsContentUtils { */ static bool HttpsStateIsModern(Document* aDocument); + /** + * Returns true of the document's URI is a .onion + */ + static bool DocumentHasOnionURI(Document* aDocument); + /** * Try to upgrade an element. * https://html.spec.whatwg.org/multipage/custom-elements.html#concept-try-upgrade diff --git a/dom/base/nsGlobalWindowOuter.cpp b/dom/base/nsGlobalWindowOuter.cpp index 783edd02c8e92..e35ee7edfcc12 100644 --- a/dom/base/nsGlobalWindowOuter.cpp +++ b/dom/base/nsGlobalWindowOuter.cpp @@ -1690,7 +1690,8 @@ bool nsGlobalWindowOuter::ComputeIsSecureContext(Document* aDocument, return false; } - if (nsContentUtils::HttpsStateIsModern(aDocument)) { + if (nsContentUtils::HttpsStateIsModern(aDocument) || + nsContentUtils::DocumentHasOnionURI(aDocument)) { return true; } diff --git a/dom/presentation/PresentationRequest.cpp b/dom/presentation/PresentationRequest.cpp index ff3b19f40859c..276d69cad4144 100644 --- a/dom/presentation/PresentationRequest.cpp +++ b/dom/presentation/PresentationRequest.cpp @@ -465,7 +465,8 @@ bool PresentationRequest::IsProhibitMixedSecurityContexts(Document* aDocument) { nsCOMPtr doc = aDocument; while (doc && !nsContentUtils::IsChromeDoc(doc)) { - if (nsContentUtils::HttpsStateIsModern(doc)) { + if (nsContentUtils::HttpsStateIsModern(doc) || + nsContentUtils::DocumentHasOnionURI(doc)) { return true; } diff --git a/dom/security/nsMixedContentBlocker.cpp b/dom/security/nsMixedContentBlocker.cpp index c6b5913537f90..2bbc2e8aecb3c 100644 --- a/dom/security/nsMixedContentBlocker.cpp +++ b/dom/security/nsMixedContentBlocker.cpp @@ -728,8 +728,8 @@ nsresult nsMixedContentBlocker::ShouldLoad( return NS_OK; } - // Check the parent scheme. If it is not an HTTPS page then mixed content - // restrictions do not apply. + // Check the parent scheme. If it is not an HTTPS or .onion page then mixed + // content restrictions do not apply. bool parentIsHttps; nsCOMPtr innerRequestingLocation = NS_GetInnermostURI(requestingLocation); @@ -746,6 +746,29 @@ nsresult nsMixedContentBlocker::ShouldLoad( return NS_OK; } if (!parentIsHttps) { + nsAutoCString parentHost; + rv = innerRequestingLocation->GetHost(parentHost); + if (NS_FAILED(rv)) { + NS_ERROR("requestingLocation->GetHost failed"); + *aDecision = REJECT_REQUEST; + return NS_OK; + } + + bool parentIsOnion = + StringEndsWith(parentHost, NS_LITERAL_CSTRING(".onion")); + if (!parentIsOnion) { + *aDecision = ACCEPT; + return NS_OK; + } + } + + bool isHttpScheme = false; + rv = innerContentLocation->SchemeIs("http", &isHttpScheme); + NS_ENSURE_SUCCESS(rv, rv); + + // .onion URLs are encrypted and authenticated. Don't treat them as mixed + // content if potentially trustworthy (i.e. whitelisted). + if (isHttpScheme && IsPotentiallyTrustworthyOnion(innerContentLocation)) { *aDecision = ACCEPT; return NS_OK; } @@ -771,10 +794,6 @@ nsresult nsMixedContentBlocker::ShouldLoad( return NS_OK; } - bool isHttpScheme = false; - rv = innerContentLocation->SchemeIs("http", &isHttpScheme); - NS_ENSURE_SUCCESS(rv, rv); - if (isHttpScheme && IsPotentiallyTrustworthyOrigin(innerContentLocation)) { *aDecision = ACCEPT; return NS_OK; diff --git a/security/manager/ssl/nsSecureBrowserUIImpl.cpp b/security/manager/ssl/nsSecureBrowserUIImpl.cpp index 4c2a19fa2d849..ea1dfca20b6b5 100644 --- a/security/manager/ssl/nsSecureBrowserUIImpl.cpp +++ b/security/manager/ssl/nsSecureBrowserUIImpl.cpp @@ -9,6 +9,7 @@ #include "mozilla/Logging.h" #include "mozilla/Unused.h" #include "mozilla/dom/Document.h" +#include "mozilla/dom/nsMixedContentBlocker.h" #include "nsContentUtils.h" #include "nsIChannel.h" #include "nsDocShell.h" @@ -246,7 +247,10 @@ static nsresult URICanBeConsideredSecure( return rv; } - canBeConsideredSecure = isHttps; + bool isOnion = + nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(innermostURI); + + canBeConsideredSecure = isHttps || isOnion; return NS_OK; } @@ -311,24 +315,35 @@ nsresult nsSecureBrowserUIImpl::UpdateStateAndSecurityInfo(nsIChannel* channel, if (NS_FAILED(rv)) { return rv; } - // If the security state is STATE_IS_INSECURE, the TLS handshake never - // completed. Don't set any further state. - if (mState == STATE_IS_INSECURE) { - return NS_OK; + // Skip setting some state if mState == STATE_IS_INSECURE (TLS handshake + // never completed). But do not return in that case, since a + // STATE_IS_INSECURE can still be changed later to STATE_IS_SECURE if it's + // routed over tor (.onion). + if (mState != STATE_IS_INSECURE) { + mTopLevelSecurityInfo = securityInfo; + MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, + (" set mTopLevelSecurityInfo")); + bool isEV; + rv = mTopLevelSecurityInfo->GetIsExtendedValidation(&isEV); + if (NS_FAILED(rv)) { + return rv; + } + if (isEV) { + MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, (" is EV")); + mState |= STATE_IDENTITY_EV_TOPLEVEL; + } } + } - mTopLevelSecurityInfo = securityInfo; - MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, - (" set mTopLevelSecurityInfo")); - bool isEV; - rv = mTopLevelSecurityInfo->GetIsExtendedValidation(&isEV); - if (NS_FAILED(rv)) { - return rv; - } - if (isEV) { - MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, (" is EV")); - mState |= STATE_IDENTITY_EV_TOPLEVEL; + // any protocol routed over tor is secure + if ((mState & STATE_IS_SECURE) == 0) { + if (nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(uri)) { + MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, (" URI is onion")); + mState = STATE_IS_SECURE; } + } + + if (mState != STATE_IS_INSECURE) { // Proactively check for mixed content in case GetState() is never called // (this can happen when loading from the BF cache). CheckForMixedContent(); -- GitLab