From e6a17bc74338297fe345121a9a03196f6843a2e1 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Fri, 17 Dec 2021 17:53:15 +1100 Subject: [PATCH 1/2] Force the MIME type for .js files to be text/javascript, to override silly OS databases/registries with incorrect settings, which Flask would otherwise depend on --- cli/onionshare_cli/web/web.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cli/onionshare_cli/web/web.py b/cli/onionshare_cli/web/web.py index cf65b69e..4f0625a0 100644 --- a/cli/onionshare_cli/web/web.py +++ b/cli/onionshare_cli/web/web.py @@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ import logging +import mimetypes import os import queue import requests @@ -80,6 +81,16 @@ class Web: self.settings = mode_settings + # Flask guesses the MIME type of files from a database on the operating + # system. + # Some operating systems, or applications that can modify the database + # (such as the Windows Registry) can treat .js files as text/plain, + # which breaks the chat app due to X-Content-Type-Options: nosniff. + # + # It's probably #notourbug but we can fix it by forcing the mimetype. + # https://github.com/onionshare/onionshare/issues/1443 + mimetypes.add_type('text/javascript', '.js') + # The flask app self.app = Flask( __name__, From 99023a8702134fffb1b2cfc9a588b8dfa3a52e53 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Fri, 17 Dec 2021 17:59:34 +1100 Subject: [PATCH 2/2] Test javascript MIME type in different modes --- desktop/tests/gui_base_test.py | 7 +++++++ desktop/tests/test_gui_chat.py | 1 + desktop/tests/test_gui_receive.py | 1 + desktop/tests/test_gui_share.py | 1 + 4 files changed, 10 insertions(+) diff --git a/desktop/tests/gui_base_test.py b/desktop/tests/gui_base_test.py index 9fbb4309..2bf762e1 100644 --- a/desktop/tests/gui_base_test.py +++ b/desktop/tests/gui_base_test.py @@ -177,6 +177,13 @@ class GuiBaseTest(unittest.TestCase): tab.get_mode().toggle_history.click() self.assertEqual(tab.get_mode().history.isVisible(), not currently_visible) + def javascript_is_correct_mime_type(self, tab, file): + """Test that the javascript file send.js is fetchable and that its MIME type is correct""" + path = f"{tab.get_mode().web.static_url_path}/js/{file}" + url = f"http://127.0.0.1:{tab.app.port}/{path}" + r = requests.get(url) + self.assertTrue(r.headers["Content-Type"].startswith("text/javascript;")) + def history_indicator(self, tab, indicator_count="1"): """Test that we can make sure the history is toggled off, do an action, and the indicator works""" # Make sure history is toggled off diff --git a/desktop/tests/test_gui_chat.py b/desktop/tests/test_gui_chat.py index 786782f7..ee6c0787 100644 --- a/desktop/tests/test_gui_chat.py +++ b/desktop/tests/test_gui_chat.py @@ -61,6 +61,7 @@ class TestChat(GuiBaseTest): tab = self.new_chat_tab() self.run_all_chat_mode_started_tests(tab) self.view_chat(tab) + self.javascript_is_correct_mime_type(tab, "chat.js") self.change_username(tab) self.run_all_chat_mode_stopping_tests(tab) self.close_all_tabs() diff --git a/desktop/tests/test_gui_receive.py b/desktop/tests/test_gui_receive.py index ca69c957..8c1c44b3 100644 --- a/desktop/tests/test_gui_receive.py +++ b/desktop/tests/test_gui_receive.py @@ -122,6 +122,7 @@ class TestReceive(GuiBaseTest): def run_all_receive_mode_tests(self, tab): """Submit files and messages in receive mode and stop the share""" self.run_all_receive_mode_setup_tests(tab) + self.javascript_is_correct_mime_type(tab, "receive.js") self.upload_file(tab, self.tmpfile_test, "test.txt") self.history_widgets_present(tab) self.counter_incremented(tab, 1) diff --git a/desktop/tests/test_gui_share.py b/desktop/tests/test_gui_share.py index 2cc48d17..ba175fa9 100644 --- a/desktop/tests/test_gui_share.py +++ b/desktop/tests/test_gui_share.py @@ -197,6 +197,7 @@ class TestShare(GuiBaseTest): self.tmpfile_test ) self.web_page(tab, "Total size") + self.javascript_is_correct_mime_type(tab, "send.js") self.download_share(tab) self.history_widgets_present(tab) self.server_is_stopped(tab)