From 5260912c3ba4277a703dc6c4176b2ff58e97d932 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Wed, 19 Nov 2025 10:54:39 +0000 Subject: [PATCH] Add admin configurable Access-Control-Allow-Origin. Signed-off-by: Jason Volk --- src/core/config/mod.rs | 11 +++++++++++ src/router/layers.rs | 36 +++++++++++++++++++++++++++--------- tuwunel-example.toml | 9 +++++++++ 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs index 6e7b44b3..4a16136e 100644 --- a/src/core/config/mod.rs +++ b/src/core/config/mod.rs @@ -2044,6 +2044,17 @@ pub struct Config { #[serde(default)] pub allow_invalid_tls_certificates: bool, + /// Sets the `Access-Control-Allow-Origin` header included by this server in + /// all responses. A list of multiple values can be specified. The default + /// is an empty list. The actual header defaults to `*` upon an empty list. + /// + /// There is no reason to configure this without specific intent. Incorrect + /// values may degrade or disrupt clients. + /// + /// default: [] + #[serde(default)] + pub access_control_allow_origin: BTreeSet, + /// Backport state-reset security fixes to all room versions. /// /// This option applies the State Resolution 2.1 mitigation developed during diff --git a/src/router/layers.rs b/src/router/layers.rs index dc43aea3..b8f2dc3c 100644 --- a/src/router/layers.rs +++ b/src/router/layers.rs @@ -12,7 +12,7 @@ use http::{ use tower::ServiceBuilder; use tower_http::{ catch_panic::CatchPanicLayer, - cors::{self, CorsLayer}, + cors::{AllowOrigin, CorsLayer}, sensitive_headers::SetSensitiveHeadersLayer, set_header::SetResponseHeaderLayer, timeout::{RequestBodyTimeoutLayer, ResponseBodyTimeoutLayer, TimeoutLayer}, @@ -138,30 +138,48 @@ fn compression_layer(server: &Server) -> tower_http::compression::CompressionLay compression_layer } -fn cors_layer(_server: &Server) -> CorsLayer { +fn cors_layer(server: &Server) -> CorsLayer { const METHODS: [Method; 7] = [ + Method::DELETE, Method::GET, Method::HEAD, + Method::OPTIONS, Method::PATCH, Method::POST, Method::PUT, - Method::DELETE, - Method::OPTIONS, ]; let headers: [HeaderName; 5] = [ - header::ORIGIN, - HeaderName::from_lowercase(b"x-requested-with").unwrap(), - header::CONTENT_TYPE, header::ACCEPT, header::AUTHORIZATION, + header::CONTENT_TYPE, + header::ORIGIN, + HeaderName::from_lowercase(b"x-requested-with").unwrap(), ]; + let allow_origin_list = server + .config + .access_control_allow_origin + .iter() + .map(AsRef::as_ref) + .map(HeaderValue::from_str) + .filter_map(Result::ok); + + let allow_origin = if !server + .config + .access_control_allow_origin + .is_empty() + { + AllowOrigin::list(allow_origin_list) + } else { + AllowOrigin::any() + }; + CorsLayer::new() - .allow_origin(cors::Any) + .max_age(Duration::from_secs(86400)) .allow_methods(METHODS) .allow_headers(headers) - .max_age(Duration::from_secs(86400)) + .allow_origin(allow_origin) } fn body_limit_layer(server: &Server) -> DefaultBodyLimit { diff --git a/tuwunel-example.toml b/tuwunel-example.toml index 7f10476a..6d4ba132 100644 --- a/tuwunel-example.toml +++ b/tuwunel-example.toml @@ -1754,6 +1754,15 @@ # #config_reload_signal = true +# Sets the `Access-Control-Allow-Origin` header included by this server in +# all responses. A list of multiple values can be specified. The default +# is an empty list. The actual header defaults to `*` upon an empty list. +# +# There is no reason to configure this without specific intent. Incorrect +# values may degrade or disrupt clients. +# +#access_control_allow_origin = [] + # Backport state-reset security fixes to all room versions. # # This option applies the State Resolution 2.1 mitigation developed during