Skip to content

Commit 2281a20

Browse files
committed
Security: Remember hosts with ignored cert errors for load status
Without this change, we only set a flag when a certificate error occurred. However, when the same certificate error then happens a second time (e.g. because of a reload or opening the same URL again), we then colored the URL as success_https (i.e. green) again. See #5403 (cherry picked from commit 021ab57)
1 parent b1e142e commit 2281a20

File tree

3 files changed

+17
-9
lines changed

3 files changed

+17
-9
lines changed

Diff for: qutebrowser/browser/browsertab.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,13 @@ class AbstractTab(QWidget):
866866
# arg 1: The exit code.
867867
renderer_process_terminated = pyqtSignal(TerminationStatus, int)
868868

869+
# Hosts for which a certificate error happened. Shared between all tabs.
870+
#
871+
# Note that we remember hosts here, without scheme/port:
872+
# QtWebEngine/Chromium also only remembers hostnames, and certificates are
873+
# for a given hostname anyways.
874+
_insecure_hosts = set() # type: typing.Set[str]
875+
869876
def __init__(self, *, win_id: int, private: bool,
870877
parent: QWidget = None) -> None:
871878
self.is_private = private
@@ -883,7 +890,6 @@ def __init__(self, *, win_id: int, private: bool,
883890
self._layout = miscwidgets.WrapperLayout(self)
884891
self._widget = None # type: typing.Optional[QWidget]
885892
self._progress = 0
886-
self._has_ssl_errors = False
887893
self._load_status = usertypes.LoadStatus.none
888894
self._tab_event_filter = eventfilter.TabEventFilter(
889895
self, parent=self)
@@ -971,7 +977,6 @@ def _on_url_changed(self, url: QUrl) -> None:
971977
@pyqtSlot()
972978
def _on_load_started(self) -> None:
973979
self._progress = 0
974-
self._has_ssl_errors = False
975980
self.data.viewing_source = False
976981
self._set_load_status(usertypes.LoadStatus.loading)
977982
self.load_started.emit()
@@ -1031,9 +1036,12 @@ def _update_load_status(self, ok: bool) -> None:
10311036
Needs to be called by subclasses to trigger a load status update, e.g.
10321037
as a response to a loadFinished signal.
10331038
"""
1034-
if ok and not self._has_ssl_errors:
1039+
if ok:
10351040
if self.url().scheme() == 'https':
1036-
self._set_load_status(usertypes.LoadStatus.success_https)
1041+
if self.url().host() in self._insecure_hosts:
1042+
self._set_load_status(usertypes.LoadStatus.warn)
1043+
else:
1044+
self._set_load_status(usertypes.LoadStatus.success_https)
10371045
else:
10381046
self._set_load_status(usertypes.LoadStatus.success)
10391047
elif ok:

Diff for: qutebrowser/browser/webengine/webenginetab.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1423,9 +1423,9 @@ def _on_load_finished(self, ok: bool) -> None:
14231423

14241424
@pyqtSlot(certificateerror.CertificateErrorWrapper)
14251425
def _on_ssl_errors(self, error):
1426-
self._has_ssl_errors = True
1427-
14281426
url = error.url()
1427+
self._insecure_hosts.add(url.host())
1428+
14291429
log.webview.debug("Certificate error: {}".format(error))
14301430

14311431
if error.is_overridable():

Diff for: qutebrowser/browser/webkit/webkittab.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -851,9 +851,9 @@ def _on_navigation_request(self, navigation):
851851
if navigation.is_main_frame:
852852
self.settings.update_for_url(navigation.url)
853853

854-
@pyqtSlot()
855-
def _on_ssl_errors(self):
856-
self._has_ssl_errors = True
854+
@pyqtSlot('QNetworkReply*')
855+
def _on_ssl_errors(self, reply):
856+
self._insecure_hosts.add(reply.url().host())
857857

858858
def _connect_signals(self):
859859
view = self._widget

0 commit comments

Comments
 (0)