tgstate-rust / src /middleware /security_headers.rs
bhgi's picture
Deploy tgstate-rust
71217a7
Raw
History Blame Contribute Delete
2.07 kB
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
}