# HTTP Security Headers: A Practical Guide to HSTS, CSP, and the Rest

> A handful of response headers quietly decide whether your site can be framed, downgraded, or injected into. Here's what HSTS, CSP, X-Frame-Options and friends do, and how to tell if yours are set right.

- URL: https://www.pyalm.com/blog/http-security-headers-guide-hsts-csp
- Author: Fadhil Abdulla
- Category: Pyalm Guard
- Published: 2026-07-07
- Updated: 2026-07-07

---

Security headers are the cheapest hardening you'll ever ship: a few lines of server config that tell the browser how to defend your users. Miss them and you leave the door open to clickjacking, protocol downgrades, and script injection. Here's what the important ones do.

## HSTS — force HTTPS, always

`Strict-Transport-Security` tells the browser to only ever reach your site over HTTPS, even if a user types `http://` or clicks an old link. That closes the downgrade window an attacker needs for a man-in-the-middle.

```
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
```

Set a long `max-age`, add `includeSubDomains` once you're sure every subdomain does HTTPS, and consider `preload` to be hardcoded into browsers.

## CSP — the big one against injection

`Content-Security-Policy` is the strongest defence against cross-site scripting (XSS). It whitelists where scripts, styles, images, and frames may load from, so an injected `<script>` from an unapproved origin simply doesn't run.

```
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'none'
```

CSP is also the most involved to deploy — start in `Content-Security-Policy-Report-Only` mode, watch what it *would* block, then enforce. Avoid `'unsafe-inline'` for scripts; it defeats much of the point.

## X-Frame-Options / frame-ancestors — stop clickjacking

If an attacker can load your page in a hidden `<iframe>` over their own, they can trick users into clicking things they can't see. `X-Frame-Options: DENY` (or the modern `frame-ancestors 'none'` in CSP) prevents your pages from being framed by other sites.

## The supporting cast

- **`X-Content-Type-Options: nosniff`** — stops the browser from guessing (and mis-executing) content types.
- **`Referrer-Policy: strict-origin-when-cross-origin`** — trims how much URL data leaks to other sites.
- **`Permissions-Policy`** — disables features you don't use (camera, microphone, geolocation) so a compromise can't reach them.

## Cookies count too

Headers protect the transport; cookie flags protect the session. Set `Secure` (HTTPS only), `HttpOnly` (hidden from JavaScript), and an appropriate `SameSite` value on session cookies — otherwise the headers above are guarding a door with the window open.

## Grade what you're actually sending

Header config drifts: a CSP gets loosened for a quick fix, a new subdomain ships without HSTS, a reverse proxy strips a header nobody notices. [**Pyalm Guard**](https://www.pyalm.com/products/guard) checks your HTTP security headers, assigns each a letter grade, and reports missing or weak ones alongside your TLS configuration. [Scan a site you own](https://guard.pyalm.com).

## Related reading

[Assess your site with Pyalm Guard](https://www.pyalm.com/products/guard) | [Introducing Pyalm Guard](https://www.pyalm.com/blog/introducing-pyalm-guard-security-posture-assessment) | [Subdomain takeover explained](https://www.pyalm.com/blog/subdomain-takeover-explained-detect-prevent) | [SPF, DKIM & DMARC explained](https://www.pyalm.com/blog/spf-dkim-dmarc-explained-stop-email-spoofing)
