Claude Fable 5.1 & GPT-6 Astra packages are live

Headers

Free

HTTP security headers that actually matter — CSP, HSTS, frame protection, and the deprecated ones still being copied from old blog posts.

227 lines8.4 KB Mistral Security
targetModels
Mistral Medium 3.5Mistral Large 3Mistral Small 4Mistral FamilyFuture Mistral Models
name
headers
category
Security
description
HTTP security headers that actually matter — CSP, HSTS, frame protection, and the deprecated ones still being copied from old blog posts.
license
MIT
author
Agent.md maintainers
last-verified
reviewed-by
unreviewed
<!-- Generated from models/_canonical by scripts/build-model-variants.js. Edit the canonical source, not this file. Behavioural profile for Mistral: scripts/model-profiles.json -->

#How to apply this file

Each section opens with one imperative line; apply every rule in the section it introduces. Do not summarise or skip a section.


#Purpose

Rules for the response headers that constrain browser behaviour. Headers are cheap and deployable independently of application changes — but they are mitigations, not fixes. A strong CSP limits the damage of an XSS; it does not remove it.


#The set worth sending

[INST] Apply every rule in this section: The set worth sending. [/INST]

css
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{RANDOM}' 'strict-dynamic'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin
HeaderPreventsNotes
Content-Security-PolicyXSS execution, injection of scriptsThe highest-value header; see Security/xss
Strict-Transport-SecurityProtocol downgrade, cookie interceptionHTTPS only; see below
X-Content-Type-OptionsMIME sniffing turning an upload into HTMLAlways nosniff
Referrer-PolicyLeaking paths and tokens via Refererstrict-origin-when-cross-origin
Permissions-PolicyUnwanted device and API accessDeny by default, allow explicitly
Cross-Origin-Opener-PolicyCross-window scripting; enables isolationsame-origin
Cross-Origin-Resource-PolicyCross-origin embedding of your resourcessame-origin

#HSTS

[INST] Apply every rule in this section: HSTS. [/INST]

max-age=31536000 (one year) with includeSubDomains.

Never add preload casually. Submission to the browser preload list is effectively irreversible on a useful timescale — every subdomain must serve HTTPS forever. Verify every subdomain first, including internal and legacy hosts.

Send HSTS only over HTTPS. A browser ignores it on a plaintext response, and sending it there suggests a misconfiguration.

#frame-ancestors over X-Frame-Options

[INST] Apply every rule in this section: frame-ancestors over X-Frame-Options. [/INST]

frame-ancestors 'none' in CSP supersedes X-Frame-Options: DENY. Keep X-Frame-Options only for very old browsers; it takes no list of origins and its ALLOW-FROM value is not supported anywhere current.


#Deprecated — remove these

[INST] Apply every rule in this section: Deprecated — remove these. [/INST]

HeaderStatus
X-XSS-ProtectionRemove. The auditor is gone from every current browser. 1; mode=block historically introduced its own vulnerabilities. Set 0 only if a legacy proxy adds it.
Expect-CTRemove. Certificate Transparency is now enforced by default.
Public-Key-Pins (HPKP)Never use. Removed from browsers; a mistake bricked sites for the pin lifetime.
X-Frame-Options: ALLOW-FROMUnsupported. Use frame-ancestors.

Copying a header block from an old article is how these persist. Check each against current browser support before shipping it.


#Why CSP is the one that matters

[INST] Apply every rule in this section: Why CSP is the one that matters. [/INST]

Of the headers above, Content-Security-Policy is the only one that changes what an attacker can achieve rather than merely what a browser reveals. The others close narrow gaps; CSP constrains script execution itself, which is why it is worth the deployment effort the rest do not require.

That effort is real. A strict policy will break inline scripts, inline styles and third-party widgets that were working, which is why the report-only phase below is not optional advice — it is how the policy gets deployed at all.

#Setting them

[INST] Apply every rule in this section: Setting them. [/INST]

Set headers at one layer — the application, or the edge — not both. Duplicated and conflicting headers behave inconsistently across browsers and proxies.

js
import helmet from "helmet";

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", (req, res) => `'nonce-${res.locals.nonce}'`, "'strict-dynamic'"],
      objectSrc: ["'none'"],
      baseUri: ["'none'"],
      frameAncestors: ["'none'"],
    },
  },
  hsts: { maxAge: 31536000, includeSubDomains: true },
  referrerPolicy: { policy: "strict-origin-when-cross-origin" },
}));

The nonce must be generated per response with a CSPRNG and never reused:

js
app.use((req, res, next) => {
  res.locals.nonce = crypto.randomBytes(16).toString("base64");
  next();
});

Never hard-code a nonce or derive it from anything predictable. A static nonce is equivalent to 'unsafe-inline'.


#Cookies

[INST] Apply every rule in this section: Cookies. [/INST]

Cookie attributes are security headers by another name:

ini
Set-Cookie: sid=…; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=1209600

Prefix a session cookie with __Host- where you can: the browser then enforces Secure, Path=/ and the absence of Domain, which prevents a subdomain from setting a cookie your application will trust.


#Caching sensitive responses

[INST] Apply every rule in this section: Caching sensitive responses. [/INST]

yaml
Cache-Control: no-store

Authenticated responses must not be cached by browsers or shared proxies. no-store is the correct directive; no-cache still permits storage with revalidation.


#Verifying

[INST] Apply every rule in this section: Verifying. [/INST]

Test the deployed origin, not the configuration file — a proxy may add, strip or override headers:

bash
curl -sI https://app.example.com | grep -iE 'content-security|strict-transport|x-content-type|referrer|permissions'

Then check the report from a scanner such as Mozilla Observatory or securityheaders.com, and deploy CSP in Report-Only with a report-to endpoint before enforcing.


#Anti-patterns

[INST] Apply every rule in this section: Anti-patterns. [/INST]

Anti-patternWhy it failsFix
script-src 'unsafe-inline'Disables most of CSP's valuePer-response nonce
Static or reused nonceEquivalent to unsafe-inlineCSPRNG per response
X-XSS-Protection: 1; mode=blockAuditor removed; introduced its own bugsRemove it
HSTS preload without auditing subdomainsEffectively irreversibleVerify every subdomain first
HSTS sent over HTTPIgnored by browsersHTTPS responses only
Headers set at both app and edgeDuplicates behave inconsistentlyChoose one layer
Copying a 2016 header blockShips deprecated headersCheck current support
no-cache on authenticated pagesStill permits storageno-store
CSP enforced without a report phaseBreaks the site on deployReport-Only first

#Checklist

  • Verify: CSP set with a per-response CSPRNG nonce and strict-dynamic
  • Verify: No 'unsafe-inline' or 'unsafe-eval' in script-src
  • Verify: object-src 'none', base-uri 'none', frame-ancestors 'none' present
  • Verify: HSTS max-age ≥ 1 year with includeSubDomains, HTTPS only
  • Verify: preload used only after auditing every subdomain
  • Verify: X-Content-Type-Options: nosniff on every response
  • Verify: Referrer-Policy set to strict-origin-when-cross-origin or stricter
  • Verify: Permissions-Policy denies unused device APIs
  • Verify: X-XSS-Protection, Expect-CT and HPKP are absent
  • Verify: Session cookies use HttpOnly, Secure, SameSite and __Host- where possible
  • Verify: Authenticated responses send Cache-Control: no-store
  • Verify: Headers are set at exactly one layer and verified against the live origin