What this baseline is (and is not)
This is a defensive baseline for a typical public website. It reduces common risks like XSS impact, session theft, clickjacking, and accidental plaintext transport. It will not “solve security” by itself, but it removes easy wins.
Cookie safety: HttpOnly, Secure, SameSite
If your site has sessions, cookies are part of your security boundary. A safe default is: Secure + HttpOnly + SameSite, with domain/path scoping kept minimal.
Cookie rules
- Secure: send only over HTTPS.
- HttpOnly: prevent JavaScript from reading session cookies.
- SameSite: reduce CSRF risk (Lax is common; Strict for high-sensitivity contexts).
- Short session lifetime + rotation on privilege changes.
Security headers baseline
Security headers are a low-cost way to enforce safer defaults in browsers. Treat them as “seatbelts”: they reduce blast radius when something else goes wrong.
Good starting set
- Strict-Transport-Security (HSTS): enforce HTTPS.
- X-Content-Type-Options: stop MIME sniffing.
- Referrer-Policy: control referrer leakage.
- Permissions-Policy: limit sensors and powerful APIs.
- Content-Security-Policy (CSP): reduce XSS impact (requires careful tuning).
CSP: practical approach
CSP is powerful but easy to break if you copy random policies. Start in Report-Only mode, observe what the site needs, then move to enforcement.
# Example CSP (starter, needs tuning for your site) Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' https: data:; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; upgrade-insecure-requests;
Note: 'unsafe-inline' for styles is a compromise many sites use initially. For stronger CSP, move toward nonces/hashes and avoid inline scripts.
Apache examples
# Apache (example) Header always set X-Content-Type-Options "nosniff" Header always set Referrer-Policy "strict-origin-when-cross-origin" Header always set X-Frame-Options "DENY" Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()" Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" # CSP (start as Report-Only first, then enforce) Header set Content-Security-Policy-Report-Only "default-src 'self'; img-src 'self' https: data:; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" # When ready: # Header set Content-Security-Policy "default-src 'self'; ..."
Nginx examples
# Nginx (example) add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header X-Frame-Options "DENY" always; add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; # CSP (start as Report-Only) add_header Content-Security-Policy-Report-Only "default-src 'self'; img-src 'self' https: data:; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" always;
TLS and HTTPS basics
HTTPS is table stakes. Ensure certificate renewal is automated and monitored. Use modern TLS defaults from your hosting provider, and avoid custom weak cipher suites.
HTTPS baseline
- Automatic certificate renewal + alerting if renewal fails.
- Redirect HTTP to HTTPS. Then set HSTS after verifying everything works.
- Disable legacy protocols (TLS 1.0/1.1) if your stack allows it.
How to test safely
- Use a staging environment for header/CSP changes if possible.
- Start CSP in Report-Only mode, gather reports, then tighten.
- Check that login/session flows still work after cookie changes.
- Measure: fewer inline scripts, fewer third-party domains.
References
- OWASP: secure headers, session management, and CSP guidance.
- Browser documentation on CSP and Permissions-Policy.
- HSTS best practices and rollout considerations.
Scope note
This guide focuses on defensive hardening and incident readiness. Guidance about hiding wrongdoing, destroying evidence, or evading lawful investigation is intentionally not provided.