Security

HSTS

HTTP Strict Transport Security (HSTS) is a security policy that forces browsers to only interact with websites over HTTPS, preventing protocol downgrade attacks and cookie hijacking.

What is HSTS?

HTTP Strict Transport Security (HSTS) is a web security policy mechanism that protects websites against protocol downgrade attacks and cookie hijacking. When a server sends an HSTS header, it instructs browsers to only communicate with the site using secure HTTPS connections, never via insecure HTTP. This policy persists in browsers for a specified duration, protecting users even when they manually type “http://” in the address bar or follow HTTP links.

HSTS solves a fundamental security problem: even when websites implement HTTPS, users often access them initially via HTTP through bookmarks, manual entry, or external links. Attackers exploit this initial HTTP connection to intercept traffic before the HTTPS redirect occurs—a technique called SSL stripping. HSTS eliminates this vulnerability by instructing browsers to automatically upgrade all HTTP requests to HTTPS for the specified domain.

How HSTS Works

When a browser first visits an HSTS-enabled website over HTTPS, the server includes a Strict-Transport-Security header in the response. The browser stores this policy, remembering that this domain requires HTTPS for the duration specified in the max-age parameter. For all subsequent visits during this period, the browser automatically converts any HTTP requests to HTTPS before making network connections, preventing insecure requests from ever reaching the network.

This behavior protects against man-in-the-middle attacks occurring at network boundaries—public WiFi hotspots, compromised routers, or malicious proxies. Even if an attacker intercepts HTTP traffic or attempts SSL stripping, browsers refuse to make HTTP connections to HSTS-protected domains. The protection activates after the first successful HTTPS visit, requiring only one secure connection to establish the policy.

// Server setting HSTS header
app.use((req, res, next) => {
  res.setHeader(
    'Strict-Transport-Security',
    'max-age=31536000; includeSubDomains; preload'
  );
  next();
});

// Redirect HTTP to HTTPS before HSTS takes effect
app.use((req, res, next) => {
  if (req.protocol === 'http') {
    return res.redirect(301, `https://${req.headers.host}${req.url}`);
  }
  next();
});

HSTS Header Parameters

The Strict-Transport-Security header accepts three parameters controlling policy scope and duration. The max-age parameter (required) specifies how many seconds browsers should enforce HTTPS-only access. Common values range from 300 seconds (5 minutes) for testing to 31536000 seconds (1 year) or 63072000 seconds (2 years) for production. During this period, browsers refuse all HTTP connections to the domain, automatically upgrading them to HTTPS internally.

The includeSubDomains directive (optional) extends HSTS protection to all subdomains of the current domain. If example.com sets “includeSubDomains”, browsers enforce HTTPS for example.com, www.example.com, api.example.com, and any other subdomains. This comprehensive protection prevents attackers from exploiting insecure subdomains to compromise the main domain, but requires ensuring ALL subdomains support HTTPS before enabling.

The preload directive (optional) indicates the site wishes to be included in browsers’ HSTS preload lists—hardcoded databases of domains requiring HTTPS shipped with browsers. Preload protection activates on the very first visit, eliminating the trust-on-first-use vulnerability where the initial HTTP visit remains unprotected. However, preload inclusion represents a long-term commitment requiring months to reverse if needed.

HSTS Preload List

Browser vendors maintain centralized HSTS preload lists containing domains that request permanent HSTS enforcement. Sites submit to hstspreload.org after meeting strict requirements: serving valid SSL certificates, redirecting all HTTP traffic to HTTPS, including HSTS headers with max-age of at least one year, enabling includeSubDomains, and including the preload directive. Submissions undergo review before inclusion in Chrome’s preload list, which other browsers typically adopt.

Preload list inclusion provides maximum security by protecting users on their very first visit before any HTTPS connection establishes the HSTS policy. This eliminates the trust-on-first-use problem where attackers might intercept the initial HTTP connection before HSTS activates. Major sites like Google, Facebook, Twitter, and banking institutions use preload lists ensuring users always connect securely even when typing “http://” or following insecure links.

// Checking HSTS header from responses
async function checkHSTSPolicy(url: string) {
  const response = await fetch(
    `https://corsproxy.io/?url=${encodeURIComponent(url)}&key=your-api-key&colo=fra`
  );

  const hsts = response.headers.get('strict-transport-security');

  if (!hsts) {
    console.log('No HSTS policy found');
    return null;
  }

  // Parse HSTS parameters
  const maxAge = hsts.match(/max-age=(\d+)/)?.[1];
  const includeSubDomains = hsts.includes('includeSubDomains');
  const preload = hsts.includes('preload');

  return {
    maxAge: maxAge ? parseInt(maxAge) : 0,
    maxAgeYears: maxAge ? parseInt(maxAge) / 31536000 : 0,
    includeSubDomains,
    preload,
    raw: hsts
  };
}

// Usage
const policy = await checkHSTSPolicy('https://example.com');
console.log('HSTS policy:', policy);

However, preload list inclusion creates significant commitment and risk. Removal requests take months to propagate through browser updates, leaving sites unable to serve HTTP content during this period even if needed. Sites must ensure all subdomains support HTTPS permanently, as includeSubDomains is required for preload. Only submit to preload lists after thorough testing and absolute certainty about long-term HTTPS commitment.

Security Benefits

HSTS prevents protocol downgrade attacks where attackers intercept initial HTTP requests and serve malicious content before HTTPS redirects occur. Without HSTS, users typing “example.com” in browsers generate HTTP requests that attackers on network paths can intercept. The attacker serves fake pages, steals credentials, or injects malicious scripts before users notice the missing HTTPS padlock. HSTS eliminates this attack vector entirely by preventing HTTP connections after the first HTTPS visit.

Cookie hijacking protection represents another critical HSTS benefit. Cookies set without the Secure flag transmit over HTTP connections, allowing attackers on shared networks to steal session cookies. Even if applications set cookies securely, users might access the site via HTTP links or manual entry, causing browsers to send cookies over unencrypted connections. HSTS prevents these insecure connections, ensuring cookies only transmit over HTTPS, protecting session integrity and user authentication.

SSL stripping defense protects against sophisticated attacks where attackers intercept connections and transparently proxy HTTPS sessions while presenting HTTP to users. Without HSTS, users remain unaware of the downgrade as the site appears functional. HSTS makes SSL stripping impossible—browsers refuse the HTTP connection regardless of what attackers attempt, alerting users to the attack by blocking access entirely rather than silently allowing exploitation.

Implementation Best Practices

Start HSTS implementation with short max-age values like 300 seconds (5 minutes) for initial testing. This allows quickly recovering if problems arise without waiting extended periods for browser HSTS policies to expire. Monitor for mixed content warnings, certificate errors, or broken functionality. Gradually increase max-age to 86400 (1 day), then 604800 (1 week), and finally 31536000 (1 year) as confidence grows in the HTTPS implementation.

Test thoroughly without includeSubDomains initially, enabling it only after verifying all subdomains support HTTPS correctly. A single HTTP-only subdomain breaks when includeSubDomains activates, causing user access failures. Audit all subdomains—www, api, cdn, staging, development—ensuring each has valid SSL certificates and serves HTTPS properly. Remember that includeSubDomains affects even wildcard subdomains and future subdomains created after HSTS deployment.

// Progressive HSTS deployment
const HSTSStages = {
  testing: 'max-age=300', // 5 minutes
  staging: 'max-age=86400', // 1 day
  production: 'max-age=31536000', // 1 year
  productionWithSubdomains: 'max-age=31536000; includeSubDomains',
  preload: 'max-age=31536000; includeSubDomains; preload'
};

function getHSTSHeader(stage: keyof typeof HSTSStages): string {
  return HSTSStages[stage];
}

// Start conservative
app.use((req, res, next) => {
  res.setHeader('Strict-Transport-Security', getHSTSHeader('testing'));
  next();
});

Never enable HSTS on domains using HTTP for any functionality. HSTS breaks HTTP access completely, redirecting all requests to HTTPS. If parts of your site require HTTP, move them to separate domains not protected by HSTS. Plan HTTPS migration completely before enabling HSTS—certificate acquisition, configuration, content delivery network setup, and testing—as HSTS locks domains to HTTPS once deployed.

Common Issues and Solutions

HTTPS lockout represents the most severe HSTS issue. If HSTS is enabled with long max-age but HTTPS later breaks—expired certificates, configuration errors, or infrastructure problems—browsers refuse access for the entire max-age period. Users cannot bypass the block even by accepting certificate warnings. The only solutions are fixing HTTPS (required) or waiting for max-age expiration (potentially a year). This scenario emphasizes the importance of starting with short max-age during testing.

Mixed content blocking affects sites serving some resources over HTTP after enabling HSTS. Browsers block HTTP images, scripts, stylesheets, or other resources when the main page loads via HTTPS. HSTS with includeSubDomains extends this protection to all subdomains, potentially breaking functionality relying on HTTP resources from subdomains. Audit all asset URLs, APIs, and third-party integrations ensuring HTTPS usage before enabling HSTS.

Subdomain accessibility problems occur when includeSubDomains is enabled but some subdomains lack HTTPS support. Development servers, staging environments, or specialized subdomains using HTTP become inaccessible to users who previously visited the main domain with HSTS enabled. Move these services to entirely different domains not covered by HSTS, or implement HTTPS support before enabling includeSubDomains on the parent domain.

HSTS with CorsProxy

CorsProxy respects HSTS policies from destination servers, forwarding Strict-Transport-Security headers to clients and upgrading HTTP requests to HTTPS when accessing HSTS-protected domains. This ensures security policies propagate correctly through the proxy, maintaining the protection HSTS provides while enabling proxy functionality for legitimate use cases.

// CorsProxy preserves HSTS headers
async function fetchThroughProxy(url: string) {
  const response = await fetch(
    `https://corsproxy.io/?url=${encodeURIComponent(url)}&key=your-api-key&type=residential&colo=fra`
  );

  // HSTS header from destination passes through
  const hsts = response.headers.get('strict-transport-security');
  if (hsts) {
    console.log('Destination HSTS policy:', hsts);
    // Browser will enforce HSTS for direct future visits
  }

  return response.json();
}

When accessing HSTS-protected sites through CorsProxy, browsers receive and store the HSTS policy just as they would from direct connections. Future direct visits to those domains automatically upgrade to HTTPS per the policy, even when not using CorsProxy. This maintains security properties while providing proxy benefits for development, testing, or production scenarios requiring proxied access.

Learn More

Create a free Account to fix CORS Errors in Production

Say goodbye to CORS errors and get back to building great web applications. It's free!

CORSPROXY Dashboard

Related Terms

More in Security

Related guides

Back to Glossary