SyntaxStudy
Sign Up
Web Security HTTP Strict Transport Security (HSTS)
Web Security Beginner 1 min read

HTTP Strict Transport Security (HSTS)

HTTP Strict Transport Security (HSTS) is a web policy that instructs browsers to communicate with a server only over HTTPS, never over plain HTTP. Once a browser receives an HSTS header from a site, it automatically upgrades all future HTTP requests to HTTPS for the duration of the `max-age` directive — even before a response is received — eliminating the window for SSL-stripping attacks that intercept the initial unencrypted request. The `includeSubDomains` directive extends HSTS protection to every subdomain, preventing an attacker who controls a subdomain from serving a mixed-content page. The `preload` directive, combined with submitting your domain to the HSTS preload list (hstspreload.org), bakes your site's HSTS policy directly into Chrome, Firefox, Safari, and Edge, so the very first request is never sent over HTTP — even on a brand-new device. Rolling out HSTS safely requires care. Start with a short `max-age` (e.g., 300 seconds), verify that every asset — including third-party scripts — is served over HTTPS, then gradually increase `max-age` to at least 31,536,000 (one year) before adding `preload`. A misconfigured HSTS header with a long `max-age` can lock users out of a site for months if the HTTPS certificate lapses or a subdomain breaks.
Example
<?php
// Laravel middleware: enforce HSTS with progressive rollout

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class StrictTransportSecurity
{
    // Increase max-age as confidence grows:
    // Phase 1: 300  (5 min)  — initial testing
    // Phase 2: 86400         — one day
    // Phase 3: 2592000       — one month
    // Phase 4: 31536000      — one year + preload-eligible
    private const MAX_AGE = 31_536_000;

    public function handle(Request $request, Closure $next): Response
    {
        $response = $next($request);

        if ($request->secure()) {
            $response->headers->set(
                'Strict-Transport-Security',
                'max-age=' . self::MAX_AGE . '; includeSubDomains; preload'
            );
        }

        return $response;
    }
}

// Register in bootstrap/app.php (Laravel 11+):
// ->withMiddleware(function (Middleware $middleware) {
//     $middleware->append(StrictTransportSecurity::class);
// })

// Verify with curl:
// curl -sI https://example.com | grep -i strict