toolhq.io

All posts
7 min readby Jameel Haider

An agent skill for web security header reviews

Header reviews are the kind of task an assistant does enthusiastically and badly. There is a well known list of headers, so it will produce the list. What it tends to miss is which ones are obsolete, which ones will break your site if applied carelessly, and which absences actually matter for the kind of site you have.

A skill fixes that by writing down the judgement rather than the list.

What it depends on

Reading real response headers needs a real request:

claude mcp add --transport http toolhq https://toolhq.io/api/mcp

That provides http_headers, which returns the response headers for a URL, and ssl_check for the transport side.

The skill

Save as .claude/skills/security-headers-review/SKILL.md:

---
name: security-headers-review
description: Review the HTTP security headers of a live site and report
  what is missing, misconfigured or obsolete. Use when asked to check
  security headers, review CSP, HSTS, clickjacking or MIME sniffing
  protection, harden a site's responses, or explain a header grade.
---

# Security header review

Fetch the real headers with `http_headers` before saying anything.
Never assume a header is present because the framework usually sets it,
and never assume it is absent because you cannot think of a reason for
it.

Check the main document URL, not just the origin, and follow redirects
to the final response. Headers frequently differ between the redirect
and the page.

## What to report, in priority order

### 1. HSTS (Strict-Transport-Security)
The highest value header on a site that is already fully HTTPS.

Look for `max-age`, and treat anything under 15552000 (180 days) as
weak. Note `includeSubDomains` and `preload` separately.

**The warning that must accompany any recommendation:** HSTS applies to
every subdomain once `includeSubDomains` is set, and it cannot be
withdrawn quickly because browsers cache it for the full max-age. If any
subdomain is still HTTP only, that subdomain becomes unreachable. Never
recommend `includeSubDomains` without asking whether every subdomain is
HTTPS. Never recommend `preload` casually: removal takes months.

### 2. Content-Security-Policy
The most effective and the most dangerous to apply.

Report what is present and specifically whether it contains
`unsafe-inline` or `unsafe-eval` in `script-src`, because a policy with
either provides little protection against injected script while still
appearing to be a policy.

**Do not propose a strict CSP for an existing site as a change to make.**
It will break inline scripts, inline styles, analytics and embeds. The
correct advice is to deploy it as `Content-Security-Policy-Report-Only`
first, collect violations, then enforce. Say this every time.

Prefer a nonce or hash based policy over a host allowlist. Note that
`frame-ancestors` in CSP supersedes X-Frame-Options.

### 3. X-Content-Type-Options
Should be `nosniff`. No downside, no configuration, no reason to omit
it. Always flag its absence.

### 4. Referrer-Policy
`strict-origin-when-cross-origin` is a sensible default and is what
most browsers now do anyway. Flag `unsafe-url`, which leaks full paths
to third parties, as a real finding.

### 5. X-Frame-Options
Only report this as missing if there is no `frame-ancestors` in a CSP.
If `frame-ancestors` is present, X-Frame-Options is redundant for modern
browsers and its absence is not a finding.

### 6. Permissions-Policy
Worth setting to disable features the site does not use, such as
`camera=(), microphone=(), geolocation=()`. Low severity. Report as an
improvement, not a fault.

## Headers that are obsolete: do not recommend these

- `X-XSS-Protection` — removed from browsers. Recommending it is a
  signal the advice came from an old checklist. If present, it is not
  harmful, but do not ask for it.
- `Expect-CT` — obsolete, certificate transparency is now enforced by
  default.
- `Feature-Policy` — superseded by Permissions-Policy.
- `Public-Key-Pins` — removed, and was actively dangerous.

## Headers that are not security headers

Do not pad a report with `X-Powered-By` removal or similar as though it
were a control. Mention version disclosure once, as housekeeping, and
do not grade on it.

## Calibrate to the site

A static marketing page and an authenticated application do not need
the same report.

- No cookies and no login: CSP and HSTS matter, framing matters less.
- Session cookies: check `Secure`, `HttpOnly` and `SameSite` on
  `Set-Cookie`, and treat their absence as higher severity than any
  missing header.
- An API returning JSON: CSP is close to irrelevant. Focus on CORS,
  and specifically on whether `Access-Control-Allow-Origin` reflects
  the request origin while `Allow-Credentials` is true, which is a real
  vulnerability rather than a missing nicety.

## Report back

1. Findings ordered by actual risk for this kind of site, not by the
   order of the checklist.
2. For each: the current value, why it matters here, and the exact
   header to set.
3. Any change that carries a risk of breaking the site, flagged, with
   the safe rollout path.
4. Obsolete headers explicitly excluded, so the reader knows they were
   considered.

Why the warnings carry the weight

Three quarters of that file is cautions, and that is the right ratio.

An assistant asked to harden a site will reliably suggest a strict CSP and includeSubDomains; preload on HSTS. Both are good advice in general and both can take a site down when applied directly to production. The CSP breaks inline script on the next deploy. The HSTS preload is close to irreversible, and if a subdomain is still HTTP only it disappears for every visitor who has seen the header.

Neither risk is a secret, but neither is in the shape of a general fact a model reaches for. Writing them into the skill converts a dangerous suggestion into a safe one with a rollout plan.

The obsolete header list earns its place for a different reason. X-XSS-Protection appears in a decade of blog posts and checklists, so it is well represented in training data and still gets recommended. A skill that explicitly rules it out stops the report looking dated.

Checking the output

Run the same URL through the security headers scanner for a graded second opinion, and HTTP headers to see the raw response. If you want the reasoning behind the grades, security headers: a practical checklist covers each header, and content security policy explained goes deeper on the one that needs the most care.

For the transport side of the same review, pair this with the certificate skill in an agent skill for SSL and certificate work.

Extending it

security-headers-review/
  SKILL.md
  csp-rollout.md     report only, collecting violations, then enforcing
  cookies.md         Secure, HttpOnly, SameSite and when to use each
  cors.md            safe configurations and the credentials trap

The CORS file is worth writing early. Reflecting the request origin while allowing credentials is a genuine vulnerability that reads like a reasonable configuration, and it is the finding most worth catching automatically.