SEC-005 critical Security Headers

HTTPS-only headers (HSTS)

Strict-Transport-Security header must be present to ensure browsers always use HTTPS, preventing downgrade attacks.

Question to ask

"Can your app still be reached over plain HTTP?"

Pass criteria

  • HSTS header present on production
  • max-age >= 31536000 (1 year)
  • includeSubDomains present if applicable

Fail criteria

  • No HSTS header on production
  • max-age too short (< 6 months)
  • HTTP accessible without redirect

Verification guide

Severity: Critical

Check automatically:

  1. Check for HSTS header:
# Check Strict-Transport-Security header
curl -sI https://example.com | grep -i "strict-transport-security"

# Expected format:
# Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  1. Check Cloudflare HSTS settings:
curl -s -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID/settings/security_header" \
  -H "Authorization: Bearer $CF_API_TOKEN" | jq '.result'
  1. Check HSTS preload status:
# Check if domain is on HSTS preload list
curl -s "https://hstspreload.org/api/v2/status?domain=example.com" | jq '.status'
# "preloaded" = best, "pending" = submitted, "unknown" = not submitted

# Manual check: https://hstspreload.org/?domain=example.com
  1. Check all environments:
# Production (required)
curl -sI https://example.com | grep -i "strict-transport-security"

# Staging (recommended)
curl -sI https://staging.example.com | grep -i "strict-transport-security"

HSTS header components:

  • max-age=31536000 - 1 year minimum for preload eligibility
  • includeSubDomains - applies to all subdomains
  • preload - allows browser preload list inclusion

Pass criteria:

  • HSTS header present on production
  • max-age >= 31536000 (1 year) for production
  • includeSubDomains present (if subdomains should be HTTPS-only)
  • Preload submitted (recommended, not required)

Fail criteria:

  • No HSTS header on production
  • max-age too short (< 6 months / 15768000)
  • Missing includeSubDomains when subdomains exist
  • HTTP still accessible without redirect

Evidence to capture:

  • HSTS header value
  • max-age duration
  • Preload status
  • Cloudflare HSTS configuration

Section

13. Infrastructure Security

Observability