Case file

Every security header this site ships (and why)

A security blog that gets defaced does not lose a page. It loses its argument. So the Sentinel’s first defensive case file turns the lens on the site itself: the exact hardening headers this domain serves, why each one is present, and how a reader can verify every claim below in a terminal in under a minute. Documentation that cannot be checked is marketing.

The full policy, as served

This is the actual header set deployed for every response — the same text ships in the site’s _headers file for Cloudflare Pages:

Content-Security-Policy:
  default-src 'self';
  img-src 'self' data:;
  style-src 'self';
  script-src 'self';
  font-src 'self';
  connect-src 'self';
  object-src 'none';
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';
  upgrade-insecure-requests
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()

(The line breaks above are for readability; the served header is a single line. curl -sI https://quietsentinelshadow.com shows it verbatim once the site is live.)

Why each directive earns its place

script-src 'self' — the big one. The site contains exactly one script: a small progressive-enhancement file served from this origin (externally loaded specifically so the policy needs no unsafe-inline, which would return the policy to roughly no policy). With script-src 'self' and no inline allowance, even if an attacker injected HTML into a future page, they could not execute script. Cross-site scripting is not merely mitigated; the entire class is structurally disallowed. The directive grammar and the inline-script risks are specified in the CSP Level 3 spec and explained in Mozilla’s reference.[^1]

style-src 'self' — the same discipline for stylesheets. The build pipeline is configured to emit external stylesheets rather than inline <style> blocks, which is what makes a self-only style policy possible.

default-src 'self' — the fallback: anything not explicitly listed is denied by default. New page types added to this site in future inherit denial rather than permission. A policy is only as good as its default posture.[^1]

img-src 'self' data: — images load only from this origin, plus data: URIs for the tiny inline icons some tooling emits. Animated media (the GIFs on this site) come from this origin and nowhere else.

frame-ancestors 'none' — no other site may embed this one in an iframe, closing off clickjacking as a vector. This is the modern, CSP-native control; the older X-Frame-Options: DENY is set alongside it purely for legacy user agents that never implemented frame-ancestors.[^2]

object-src 'none' — plugins and embedded objects (<object>, <embed>) are dead technology and a live injection surface. Denied.

base-uri 'self' and form-action 'self' — an injected <base> tag can silently rewrite every relative URL on a page, and an injected form can exfiltrate whatever a confused reader types into it. Both are pinned to this origin.[^1]

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload — two years of browser-enforced HTTPS, applied to every subdomain, with the preload signal for inclusion in browser-baked HSTS lists. HSTS is specified in RFC 6797.[^3]

X-Content-Type-Options: nosniff — stops browsers from guessing a content type when the declared one is missing, closing the MIME-confusion family of bugs.[^4]

Referrer-Policy: strict-origin-when-cross-origin — outbound links leak the origin, never the full URL a reader was on. Reader privacy, at zero cost.[^4]

Permissions-Policy: camera=(), microphone=(), geolocation=() — every powerful browser API this site has no conceivable use for is explicitly disabled.[^4]

Verification, not vibes

The claims above are checkable in three ways, all of which the Sentinel encourages:

$ curl -sI https://quietsentinelshadow.com | grep -i content-security
content-security-policy: default-src 'self'; img-src 'self' data:; ...
  1. The curl one-liner above, against the live site.
  2. securityheaders.com, Scott Helme’s free scanner, which grades header posture — the site is built to hold an A.
  3. Opening the browser devtools network panel; every response carries the set.

The OWASP Secure Headers Project maintains the community reference for each header’s purpose and safe values, and this configuration was checked against it during design.[^4]

The boring thesis

Nothing on this page required a product, a service, or an unusual insight. It required a static site with no server-side code, one script, and an afternoon. That is the thesis the Sentinel will keep returning to: most defenders’ threat models are covered not by exotic tooling but by defaults this boring, applied this deliberately, and documented this openly. Future files will hold this one as the baseline: if a change ever weakens the policy, it ships with a written justification or not at all.

Sources & attributions

  1. MDN Web Docs, Content Security Policy (CSP) — directive reference, including script-src, default-src, base-uri, form-actiondeveloper.mozilla.org. Specification: W3C, Content Security Policy Level 3w3.org/TR/CSP3.
  2. MDN Web Docs, CSP: frame-ancestors and X-Frame-Optionsdeveloper.mozilla.org.
  3. Hodges, J., Jackson, C., Barth, A. (eds.), HTTP Strict Transport Security (HSTS), RFC 6797, IETF, November 2012 — datatracker.ietf.org/doc/html/rfc6797. Preload list submission: hstspreload.org.
  4. OWASP Secure Headers Project — community reference for HSTS, X-Content-Type-Options, Referrer-Policy, Permissions-Policyowasp.org/www-project-secure-headers. Scanner: securityheaders.com (Scott Helme).