feat(gateway): add security headers middleware

Add security headers to all gateway responses:
- X-Frame-Options: DENY
- X-Content-Type-Options: nosniff
- Strict-Transport-Security: max-age=31536000; includeSubDomains
- Referrer-Policy: strict-origin-when-cross-origin
- Content-Security-Policy: default-src 'self'

Uses tower_http::set_header::SetResponseHeaderLayer applied globally.
Closes CRITICAL SECURITY GAP #2 from security review.
This commit is contained in:
Ashwin Kumar Sivakumar 2026-05-31 22:55:00 +05:30
parent ed80820913
commit c262e89e8f
2 changed files with 22 additions and 1 deletions

View file

@ -8,7 +8,7 @@ axum = { workspace = true }
tokio = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
tower-http = { version = "0.6", features = ["cors"] }
tower-http = { version = "0.6", features = ["cors", "set-header"] }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
reqwest = { version = "0.12", features = ["json", "stream"] }

View file

@ -9,6 +9,7 @@ use axum::{
};
use std::net::SocketAddr;
use tower_http::cors::{AllowHeaders, AllowOrigin, CorsLayer};
use tower_http::set_header::SetResponseHeaderLayer;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
#[derive(Clone)]
@ -263,6 +264,26 @@ async fn main() {
.route("/api/{*path}", any(proxy_handler))
.route("/health", any(|| async { "Gateway OK" }))
.layer(cors)
.layer(SetResponseHeaderLayer::if_not_present(
axum::http::header::X_FRAME_OPTIONS,
HeaderValue::from_static("DENY"),
))
.layer(SetResponseHeaderLayer::if_not_present(
axum::http::header::X_CONTENT_TYPE_OPTIONS,
HeaderValue::from_static("nosniff"),
))
.layer(SetResponseHeaderLayer::if_not_present(
axum::http::header::STRICT_TRANSPORT_SECURITY,
HeaderValue::from_static("max-age=31536000; includeSubDomains"),
))
.layer(SetResponseHeaderLayer::if_not_present(
axum::http::header::REFERRER_POLICY,
HeaderValue::from_static("strict-origin-when-cross-origin"),
))
.layer(SetResponseHeaderLayer::if_not_present(
axum::http::header::CONTENT_SECURITY_POLICY,
HeaderValue::from_static("default-src 'self'"),
))
.with_state(services);
let port: u16 = std::env::var("PORT")