Insecure or unset HTTP headers - Strict Transport Security
Need
Enforcement of HTTPS through a long-lived Strict-Transport-Security policy
Context
• Usage of Rust 1.75+ for building application services
• Usage of the actix-web crate for handling HTTP requests
Description
1. Non compliant code
use actix_web::middleware::DefaultHeaders;
fn security_headers() -> DefaultHeaders {
// One day of HSTS: returning users make their first request over HTTP
DefaultHeaders::new().add(("Strict-Transport-Security", "max-age=86400"))
}The `security_headers` function below sends a `Strict-Transport-Security` header with `max-age=86400`. HSTS tells the browser to use HTTPS for the domain for `max-age` seconds, even if the user types `http://` or follows an old link. A value of one day means the protection expires 24 hours after the last visit: a user who returns after a weekend makes the first request over plain HTTP, and an attacker on the network can intercept it and strip the connection down to HTTP (SSL stripping) to read credentials and cookies. `max-age=0` is worse, because it removes a policy that the browser had already stored. The header also omits `includeSubDomains`, so subdomains such as `api.` or `login.` remain reachable over HTTP.
2. Steps
• Send `Strict-Transport-Security` with a `max-age` of at least `31536000` seconds from a middleware that covers every HTTPS response.
• Add `includeSubDomains` once every subdomain is served over HTTPS.
• Never send `max-age=0` in production, since it deletes the policy stored by the browser.
• Redirect every plain HTTP request to HTTPS with a permanent redirect.
• Consider adding `preload` and submitting the domain to the HSTS preload list.
3. Secure code example
use actix_web::middleware::DefaultHeaders;
fn security_headers() -> DefaultHeaders {
// One year, renewed on every visit, including all subdomains
DefaultHeaders::new().add((
"Strict-Transport-Security",
"max-age=31536000; includeSubDomains",
))...The corrected header sets `max-age=31536000`, one year, which is the minimum recommended value and the requirement for inclusion in the browser preload lists. Every visit renews the period, so regular users are always covered. `includeSubDomains` extends the policy to every subdomain, which prevents an attacker from using a forgotten HTTP subdomain to set or read cookies for the parent domain. After confirming that every subdomain works over HTTPS, the domain can add the `preload` directive and be submitted to the HSTS preload list, so browsers enforce HTTPS even on the very first visit.