diff --git a/syncstorage/src/tokenserver/handlers.rs b/syncstorage/src/tokenserver/handlers.rs index 5080db2b..81af88f8 100644 --- a/syncstorage/src/tokenserver/handlers.rs +++ b/syncstorage/src/tokenserver/handlers.rs @@ -61,11 +61,13 @@ pub async fn get_tokenserver_result( start.duration_since(UNIX_EPOCH).unwrap().as_secs() }; - // `X-Content-Type-Options: nosniff` was set automatically by the Pyramid cornice library - // on the Python Tokenserver. For the Rust Tokenserver, we set it in nginx instead of in the - // application code here. Ok(HttpResponse::build(StatusCode::OK) .header("X-Timestamp", timestamp.to_string()) + // This header helps to prevent cross-site scripting attacks by + // blocking content type sniffing. It was set automatically by the + // Pyramid cornice library used by the Python Tokenserver, so we set + // it here for safety and consistency. + .header("X-Content-Type-Options", "nosniff") .json(result)) } diff --git a/tools/integration_tests/tokenserver/test_misc.py b/tools/integration_tests/tokenserver/test_misc.py index c82d629d..ff046c58 100644 --- a/tools/integration_tests/tokenserver/test_misc.py +++ b/tools/integration_tests/tokenserver/test_misc.py @@ -220,3 +220,15 @@ class TestMisc(TestCase, unittest.TestCase): user = self._get_user(res.json['uid']) # The user is assigned to a new node self.assertEqual(user['nodeid'], self.NODE_ID) + + def test_x_content_type_options(self): + self._add_user(generation=1234, + keys_changed_at=1234, + client_state='aaaa') + headers = self._build_auth_headers(generation=1234, + keys_changed_at=1234, + client_state='aaaa') + res = self.app.get('/1.0/sync/1.5', headers=headers) + # Tokenserver responses should include the + # `X-Content-Type-Options: nosniff` header + self.assertEqual(res.headers['X-Content-Type-Options'], 'nosniff')