4.1 KiB
name, description
| name | description |
|---|---|
| security-headers-and-tls | Use when configuring or reviewing a web server/site's HTTP security headers and TLS/SSL setup. Baseline hardening to apply on any real site, not just when explicitly requested. |
Security Headers and TLS
HTTP security headers (baseline for any real site)
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()
Content-Security-Policy: <site-specific -- see below>
- HSTS (
Strict-Transport-Security): only send this once HTTPS is confirmed fully working site-wide (including all subdomains covered byincludeSubDomains) — sending it prematurely can lock out HTTP access to a subdomain that isn't actually HTTPS-ready yet, and it's effectively irreversible for themax-ageduration for anyone who already received it. - X-Frame-Options (or the modern equivalent,
frame-ancestorsin CSP): prevents clickjacking via iframe embedding.SAMEORIGINunless the site genuinely needs to be embeddable elsewhere. - Content-Security-Policy: the highest-value header but also the
easiest to get wrong and break the site with. Build it FROM the site's
actual real asset sources (script/style/font/image origins actually in
use), don't write a generic policy and hope — a too-strict CSP silently
breaks functionality (a blocked script just doesn't run, often with no
obvious visual error). Start in
Content-Security-Policy-Report-Onlymode if there's any uncertainty, confirm no violations in real browser testing, then switch to enforcing. - CORS (
Access-Control-Allow-Origin): never*on any endpoint that reads authenticated/session state — an open CORS policy on an authenticated endpoint is a real, exploitable vulnerability, not a theoretical one.
TLS/SSL configuration strength
- Protocol versions: TLS 1.2 minimum, TLS 1.3 preferred/available. SSLv3, TLS 1.0, and TLS 1.1 should be disabled — they're broken or deprecated, not just "older."
- Cipher suites: prefer AEAD ciphers (AES-GCM, ChaCha20-Poly1305). Disable known-weak ciphers (RC4, 3DES, export-grade ciphers, anything without forward secrecy).
- Certificate: verify the chain is complete (intermediate certs included, not just the leaf), verify auto-renewal is actually working (a cert 5 days from expiry with no renewal cron running is a real incident waiting to happen, not a hypothetical), verify no mixed- content warnings (HTTP resources loaded on an HTTPS page).
- Test with a real tool, don't eyeball a config file and assume it's
correct:
openssl s_client -connect host:443 -tls1(should fail if TLS 1.0 is properly disabled), or an external scanner (SSL Labs'ssltestAPI/site) for a full grade — config files that look right can still have an inherited default or a reverse-proxy layer re-enabling something the origin server itself disabled.
Reverse-proxy-specific gotchas
If the site sits behind a reverse proxy (nginx, a proxy manager, a CDN):
security headers and TLS termination often happen at the PROXY layer,
not the origin — verify headers on the actual public-facing response,
not just what the origin server itself sends, since a proxy can add,
strip, or override headers in either direction. Confirmed real pattern
in this project: X-Forwarded-Proto set by the proxy and trusted by the
origin's own HTTPS-detection logic — get this wrong in either direction
(proxy not setting it, or origin not trusting it, or origin overwriting
an already-correct value with its own guess) and you get either broken
HTTPS detection or a spoofable header, depending on which mistake it is.
Don't apply hardening blindly
Test every header/TLS change against the real site afterward — a CSP that's too strict, an HSTS header sent too early, or a cipher suite change that drops support for a client that still needs to work are all real ways "hardening" can cause an outage. Security work still needs the same verification discipline as any other change.