diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fb3b56..7a1551a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,13 +15,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Added `/api/v1/statuses/{status_id}/thread` API endpoint (replaces `/api/v1/statuses/{status_id}/context`). - Accept webfinger requests where `resource` is instance actor ID. - Added `proxy_set_header X-Forwarded-Proto $scheme;` directive to nginx config example. +- Add `Content-Security-Policy` and `X-Content-Type-Options` headers to all responses. ### Changed - Allow `instance_uri` configuration value to contain URI scheme. -- Changed `Content-Security-Policy` header value in nginx config examples. - Changed `/api/v1/statuses/{status_id}/context` response format to match Mastodon API. - Changed status code of `/api/v1/statuses` response to 200 to match Mastodon API. +- Removed `add_header` directives for `Content-Security-Policy` and `X-Content-Type-Options` headers from nginx config example. ### Deprecated diff --git a/contrib/mitra-alt-fe.nginx b/contrib/mitra-alt-fe.nginx index 9637efc..f896aa0 100644 --- a/contrib/mitra-alt-fe.nginx +++ b/contrib/mitra-alt-fe.nginx @@ -31,8 +31,8 @@ server { ssl_stapling_verify on; add_header Strict-Transport-Security "max-age=63072000" always; - # script-src unsafe-inline required by MetaMask - # style-src oauth-authorization required by OAuth authorization page + + # CSP header can't be added in location block add_header Content-Security-Policy "default-src 'none'; connect-src 'self'; img-src 'self' data:; media-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'nonce-oauth-authorization'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'"; add_header X-Content-Type-Options "nosniff"; diff --git a/contrib/mitra.nginx b/contrib/mitra.nginx index 3ff06b9..589e7ec 100644 --- a/contrib/mitra.nginx +++ b/contrib/mitra.nginx @@ -31,10 +31,6 @@ server { ssl_stapling_verify on; add_header Strict-Transport-Security "max-age=63072000" always; - # script-src unsafe-inline required by MetaMask - # style-src oauth-authorization required by OAuth authorization page - add_header Content-Security-Policy "default-src 'none'; connect-src 'self'; img-src 'self' data:; media-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'nonce-oauth-authorization'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'"; - add_header X-Content-Type-Options "nosniff"; client_max_body_size 10M; diff --git a/src/http.rs b/src/http.rs index 0cbb1ee..12c4137 100644 --- a/src/http.rs +++ b/src/http.rs @@ -3,7 +3,11 @@ use actix_web::{ dev::{ConnectionInfo, ServiceResponse}, error::{Error, JsonPayloadError}, http::StatusCode, - middleware::{ErrorHandlerResponse, ErrorHandlers}, + middleware::{ + DefaultHeaders, + ErrorHandlerResponse, + ErrorHandlers, + }, web::{Form, Json}, Either, HttpRequest, @@ -36,6 +40,25 @@ pub fn create_auth_error_handler() -> ErrorHandlers }) } +pub fn create_default_headers_middleware() -> DefaultHeaders { + DefaultHeaders::new() + .add(( + "Content-Security-Policy", + // script-src unsafe-inline required by MetaMask + // style-src oauth-authorization required by OAuth authorization page + "default-src 'none'; \ + connect-src 'self'; \ + img-src 'self' data:; \ + media-src 'self'; \ + script-src 'self' 'unsafe-inline'; \ + style-src 'self' 'nonce-oauth-authorization'; \ + frame-ancestors 'none'; \ + base-uri 'self'; \ + form-action 'self'", + )) + .add(("X-Content-Type-Options", "nosniff")) +} + /// Convert JSON payload deserialization errors into validation errors pub fn json_error_handler( error: JsonPayloadError, diff --git a/src/main.rs b/src/main.rs index 1fbcb44..f52bf04 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,7 @@ use mitra::database::migrate::apply_migrations; use mitra::ethereum::contracts::get_contracts; use mitra::http::{ create_auth_error_handler, + create_default_headers_middleware, json_error_handler, }; use mitra::job_queue::scheduler; @@ -133,6 +134,7 @@ async fn main() -> std::io::Result<()> { } }) .wrap(create_auth_error_handler()) + .wrap(create_default_headers_middleware()) .app_data(web::PayloadConfig::default().limit(UPLOAD_MAX_SIZE * 2)) .app_data(web::JsonConfig::default() .limit(UPLOAD_MAX_SIZE * 2)