Spaces:
Paused
Paused
| use axum::extract::Request; | |
| use axum::middleware::Next; | |
| use axum::response::Response; | |
| pub async fn security_headers_middleware(request: Request, next: Next) -> Response { | |
| let is_https = request | |
| .headers() | |
| .get("x-forwarded-proto") | |
| .and_then(|v| v.to_str().ok()) | |
| .map_or(false, |v| v == "https") | |
| || request.uri().scheme_str() == Some("https"); | |
| let mut response = next.run(request).await; | |
| let headers = response.headers_mut(); | |
| // Prevent MIME sniffing | |
| headers.insert("X-Content-Type-Options", "nosniff".parse().unwrap()); | |
| // Prevent clickjacking | |
| headers.insert("X-Frame-Options", "DENY".parse().unwrap()); | |
| // No referrer leakage | |
| headers.insert("Referrer-Policy", "strict-origin-when-cross-origin".parse().unwrap()); | |
| // Disable unnecessary browser features | |
| headers.insert( | |
| "Permissions-Policy", | |
| "geolocation=(), microphone=(), camera=(), payment=(), usb=(), magnetometer=(), gyroscope=()" | |
| .parse() | |
| .unwrap(), | |
| ); | |
| // Explicitly disable the legacy XSS auditor. Modern OWASP guidance is to | |
| // send `0` here; the legacy filter in old IE/Chromium can actually be | |
| // abused to introduce XSS, and modern browsers ignore it entirely. Rely | |
| // on the strict Content-Security-Policy below instead. | |
| headers.insert("X-XSS-Protection", "0".parse().unwrap()); | |
| // Block cross-domain policies (Flash/PDF) | |
| headers.insert("X-Permitted-Cross-Domain-Policies", "none".parse().unwrap()); | |
| // Content Security Policy | |
| headers.insert( | |
| "Content-Security-Policy", | |
| "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self'; font-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'" | |
| .parse() | |
| .unwrap(), | |
| ); | |
| if is_https { | |
| headers.insert( | |
| "Strict-Transport-Security", | |
| "max-age=31536000; includeSubDomains".parse().unwrap(), | |
| ); | |
| } | |
| response | |
| } | |