Skip to content

Commit b974422

Browse files
Updated tor2web check to return an error page with a 403 status on success
1 parent ecd6b2b commit b974422

File tree

4 files changed

+36
-56
lines changed

4 files changed

+36
-56
lines changed

securedrop/source_app/__init__.py

+12-24
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import os
55
import time
66
import werkzeug
7-
from flask import (Flask, render_template, escape, flash, Markup, request, g, session,
7+
from flask import (Flask, flash, render_template, request, g, session,
88
url_for)
99
from flask_babel import gettext
1010
from flask_assets import Environment
@@ -23,7 +23,7 @@
2323
from sdconfig import SDConfig
2424
from source_app import main, info, api
2525
from source_app.decorators import ignore_static
26-
from source_app.utils import clear_session_and_redirect_to_logged_out_page
26+
from source_app.utils import clear_session_and_redirect_to_logged_out_page, get_sourcev3_url
2727

2828

2929
def get_logo_url(app: Flask) -> str:
@@ -90,28 +90,8 @@ def handle_csrf_error(e: CSRFError) -> werkzeug.Response:
9090
for module in [main, info, api]:
9191
app.register_blueprint(module.make_blueprint(config)) # type: ignore
9292

93-
@app.before_request
94-
@ignore_static
95-
def check_tor2web() -> None:
96-
# ignore_static here so we only flash a single message warning
97-
# about Tor2Web, corresponding to the initial page load.
98-
if 'X-tor2web' in request.headers:
99-
flash(
100-
Markup(
101-
'<strong>{}</strong>&nbsp;{}&nbsp;<a href="{}">{}</a>'.format(
102-
escape(gettext("WARNING:")),
103-
escape(
104-
gettext(
105-
'You appear to be using Tor2Web, which does not provide anonymity.'
106-
)
107-
),
108-
url_for('info.tor2web_warning'),
109-
escape(gettext('Why is this dangerous?')),
110-
)
111-
),
112-
"banner-warning"
113-
)
114-
93+
# before_request hooks are executed in order of declaration, so set up g object
94+
# before the potential tor2web 403 response.
11595
@app.before_request
11696
@ignore_static
11797
def setup_g() -> Optional[werkzeug.Response]:
@@ -128,6 +108,14 @@ def setup_g() -> Optional[werkzeug.Response]:
128108

129109
return None
130110

111+
@app.before_request
112+
@ignore_static
113+
def check_tor2web() -> Optional[Tuple[str, int]]:
114+
if 'X-tor2web' in request.headers:
115+
flash(gettext("Tor2Web proxies do not protect your anonymity!"), "error")
116+
return render_template('tor2web-warning.html', source_url=get_sourcev3_url()), 403
117+
return None
118+
131119
@app.errorhandler(404)
132120
def page_not_found(error: werkzeug.exceptions.HTTPException) -> Tuple[str, int]:
133121
return render_template('notfound.html'), 404

securedrop/source_app/info.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
# -*- coding: utf-8 -*-
22
import flask
3-
from flask import Blueprint, render_template, send_file, redirect, url_for
3+
from flask import Blueprint, render_template, send_file, redirect, url_for, flash
4+
from flask_babel import gettext
45
import werkzeug
56

67
from io import BytesIO # noqa
78

89
from encryption import EncryptionManager
910
from sdconfig import SDConfig
11+
from source_app.utils import get_sourcev3_url
1012

1113

1214
def make_blueprint(config: SDConfig) -> Blueprint:
1315
view = Blueprint('info', __name__)
1416

1517
@view.route('/tor2web-warning')
1618
def tor2web_warning() -> str:
17-
return render_template("tor2web-warning.html")
19+
flash(gettext("Tor2Web proxies do not protect your anonymity!"), "error")
20+
return render_template("tor2web-warning.html", source_url=get_sourcev3_url())
1821

1922
@view.route('/use-tor')
2023
def recommend_tor_browser() -> str:
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
{% extends "base.html" %}
22
{% block body %}
3-
<h1>{{ gettext('Why is there a warning about Tor2Web?') }}</h1>
4-
<p>{{ gettext('Using Tor2Web to connect to SecureDrop will not protect your anonymity.') }}</p>
5-
<p>{{ gettext('It could be possible for anyone monitoring your Internet traffic (your government, your Internet provider), to identify you.') }}
3+
<h1>{{ gettext('Tor2Web Detected') }}</h1>
4+
<div class="center">
5+
{% include 'flashed.html' %}
6+
</div>
7+
<p>{{ gettext(' If you use a Tor2Web proxy to connect to SecureDrop, anyone monitoring your Internet traffic &mdash; such as your government, your Internet provider, or the proxy operator &mdash; may be able to identify you.') }}
68
</p>
7-
<p>{{ gettext('We <strong>strongly advise</strong> you to use the <a href="www.torproject.org/projects/torbrowser.html">Tor Browser</a> instead.') }}
9+
<p>{{ gettext('Use the <a href="www.torproject.org/projects/torbrowser.html">Tor Browser</a>, and access this service directly instead. The correct onion service address is:') }}
10+
<pre>{{ source_url }}</pre>
811
</p>
9-
{% endblock %}
12+
<p> {{ gettext ('If you are using Tor Browser and have been brought to this page, generate a new identity before connecting to this service directly.') }} {{ gettext('Click the <img src={icon} alt="" width="16" height="16">&nbsp;<b>New Identity</b> button in your Tor Browser\'s toolbar. This will clear your Tor Browser activity data on this device.').format(icon=url_for('static', filename='i/torbroom-black.png')) }}
13+
</p>
14+
<p>{{ gettext('If there is a reasonable risk of your Internet traffic being monitored, you should also consider connecting from a different location or network.') }}
15+
</p>
16+
{% endblock %}

securedrop/tests/test_source.py

+7-25
Original file line numberDiff line numberDiff line change
@@ -537,38 +537,20 @@ def test_submit_sanitizes_filename(source_app):
537537
mtime=0)
538538

539539

540-
@flaky(rerun_filter=utils.flaky_filter_xfail)
541-
@pytest.mark.parametrize("locale", get_test_locales())
542-
def test_tor2web_warning_headers(config, source_app, locale):
540+
@pytest.mark.parametrize("test_url", ['main.index', 'main.create', 'main.submit'])
541+
def test_tor2web_warning_as_403(config, source_app, test_url):
543542
with source_app.test_client() as app:
544-
with InstrumentedApp(app) as ins:
545-
resp = app.get(url_for('main.index', l=locale), headers=[('X-tor2web', 'encrypted')])
546-
assert resp.status_code == 200
547-
548-
assert page_language(resp.data) == language_tag(locale)
549-
msgids = [
550-
"WARNING:",
551-
"You appear to be using Tor2Web, which does not provide anonymity.",
552-
"Why is this dangerous?",
553-
]
554-
with xfail_untranslated_messages(config, locale, msgids):
555-
ins.assert_message_flashed(
556-
'<strong>{}</strong>&nbsp;{}&nbsp;<a href="{}">{}</a>'.format(
557-
escape(gettext(msgids[0])),
558-
escape(gettext(msgids[1])),
559-
url_for('info.tor2web_warning'),
560-
escape(gettext(msgids[2])),
561-
),
562-
'banner-warning'
563-
)
564-
543+
resp = app.get(url_for(test_url), headers=[('X-tor2web', 'encrypted')])
544+
text = resp.data.decode('utf-8')
545+
assert "Tor2Web Detected" in text
565546

566547
def test_tor2web_warning(source_app):
567548
with source_app.test_client() as app:
568549
resp = app.get(url_for('info.tor2web_warning'))
569550
assert resp.status_code == 200
570551
text = resp.data.decode('utf-8')
571-
assert "Why is there a warning about Tor2Web?" in text
552+
assert "Tor2Web Detected" in text
553+
572554

573555

574556
def test_why_use_tor_browser(source_app):

0 commit comments

Comments
 (0)