Kartikeya Raowriting

Five minutes with your response headers

Contents
  1. Check what you send
  2. The headers that matter
  3. A starting config

Most sites I look at are missing at least two of these. The check takes five minutes, and the fix is usually a few lines of server config.

Check what you send

Run this against your own site. Commands have a $ prompt, and the rest is output.

terminal
curl -sI https://example.com
HTTP/2 200
content-type: text/html; charset=utf-8
strict-transport-security: max-age=63072000; includeSubDomains; preload
x-content-type-options: nosniff
referrer-policy: strict-origin-when-cross-origin
curl -sI https://example.com | grep -i content-security-policy

The copy button on that block copies just the two commands, without prompts or output. Paste them straight into your terminal.

Quick quiz: which important header is missing from the output above? Answer: . The second command printed nothing.

The headers that matter

  • Strict-Transport-Security makes browsers use HTTPS only, even when someone types http://.
  • Content-Security-Policy restricts where scripts, styles and frames can load from. It’s the strongest defence against XSS you can deploy without code changes.
  • X-Content-Type-Options: nosniff stops browsers from guessing file types.
  • Referrer-Policy keeps full URLs, including tokens in query strings, from leaking to other sites.
  • Permissions-Policy turns off browser features you don’t use, such as camera, microphone and geolocation.

A starting config

/etc/nginx/snippets/security-headers.confnginx
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'none'" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

Reload and check again:

terminal
sudo nginx -t && sudo systemctl reload nginx
nginx: configuration file /etc/nginx/nginx.conf test is successful

Press Ctrl + Shift + I in your browser, open the Network tab, and click the document request to see the same headers without a terminal.1

Footnotes

  1. On macOS it’s ⌘ + ⌥ + I. ↩