diff --git a/public/.well-known/agent-skills/index.json b/public/.well-known/agent-skills/index.json
index 668bf522..cb16dc03 100644
--- a/public/.well-known/agent-skills/index.json
+++ b/public/.well-known/agent-skills/index.json
@@ -6,7 +6,7 @@
"type": "skill-md",
"description": "Query and apply The Website Specification — a platform-agnostic specification of what a good website does. Use when the user asks what their site should have, whether something is required, how to audit a URL, what's missing for agent readiness, or anything else where you'd otherwise be guessing at web best practice. Backs answers with primary sources and ships an MCP server with search, list, fetch, checklist, and audit tools.",
"url": "/.well-known/agent-skills/specification-website/SKILL.md",
- "digest": "sha256:bba469a59dfcb3a619678878967f0cbf83f4bb95d3cd6ecd07bf8209e0d6aeaf"
+ "digest": "sha256:1506d0edc9a5ec36be2bd8c5054d4f3a9d85385d927e3bc3bc3121bcb9155205"
}
]
}
diff --git a/public/.well-known/agent-skills/specification-website/SKILL.md b/public/.well-known/agent-skills/specification-website/SKILL.md
index 3e3c52d9..acae5cfd 100644
--- a/public/.well-known/agent-skills/specification-website/SKILL.md
+++ b/public/.well-known/agent-skills/specification-website/SKILL.md
@@ -5,7 +5,7 @@ description: Query and apply The Website Specification — a platform-agnostic s
# specification.website
-The Website Specification is a single source of truth for what a good website does. Ten categories, 168 pages, every item tagged with a status. It ships in three machine-readable forms: per-page Markdown, llms.txt / llms-full.txt, and an MCP server.
+The Website Specification is a single source of truth for what a good website does. Ten categories, 169 pages, every item tagged with a status. It ships in three machine-readable forms: per-page Markdown, llms.txt / llms-full.txt, and an MCP server.
## When to use this skill
diff --git a/public/og-default.png b/public/og-default.png
index f2d92e30..6179a303 100644
Binary files a/public/og-default.png and b/public/og-default.png differ
diff --git a/public/og/checklist.png b/public/og/checklist.png
index 23c6cfb5..3bd9924a 100644
Binary files a/public/og/checklist.png and b/public/og/checklist.png differ
diff --git a/public/og/spec.png b/public/og/spec.png
index e7b9d490..d938dbd3 100644
Binary files a/public/og/spec.png and b/public/og/spec.png differ
diff --git a/public/og/spec/security.png b/public/og/spec/security.png
index 2f3df32e..f5c46914 100644
Binary files a/public/og/spec/security.png and b/public/og/spec/security.png differ
diff --git a/public/og/spec/security/fetch-metadata.png b/public/og/spec/security/fetch-metadata.png
new file mode 100644
index 00000000..db79b0dd
Binary files /dev/null and b/public/og/spec/security/fetch-metadata.png differ
diff --git a/src/content/changelog/2026-09-04-fetch-metadata.md b/src/content/changelog/2026-09-04-fetch-metadata.md
new file mode 100644
index 00000000..18c14f61
--- /dev/null
+++ b/src/content/changelog/2026-09-04-fetch-metadata.md
@@ -0,0 +1,8 @@
+---
+title: "Fetch Metadata request headers"
+date: "2026-09-04"
+type: added
+relatedSlugs: [fetch-metadata]
+---
+
+Added a page on [Fetch Metadata request headers](/spec/security/fetch-metadata/) — `Sec-Fetch-Site`, `Sec-Fetch-Mode` and `Sec-Fetch-Dest`, which browsers attach to every request and a server can read to reject cross-site traffic it never meant to serve. It is the rare entry in the security category that you consume rather than emit: setting a response header achieves nothing, and the value only appears once middleware acts on the values. OWASP now names it a primary CSRF defence, so the page is `recommended` rather than optional.
diff --git a/src/content/spec/security/cookie-attributes.md b/src/content/spec/security/cookie-attributes.md
index 692a1cd2..5e9358ce 100644
--- a/src/content/spec/security/cookie-attributes.md
+++ b/src/content/spec/security/cookie-attributes.md
@@ -6,7 +6,7 @@ summary: "Every cookie should be Secure, HttpOnly where possible, and have an ex
status: required
order: 100
appliesTo: [all]
-relatedSlugs: [https-tls, hsts, frame-ancestors, referrer-policy, clear-site-data, privacy/storage-access-api]
+relatedSlugs: [https-tls, hsts, frame-ancestors, referrer-policy, clear-site-data, fetch-metadata, privacy/storage-access-api]
updated: "2026-07-09T00:00:00.000Z"
sources:
- title: "draft-ietf-httpbis-rfc6265bis — Cookies: HTTP State Management Mechanism"
diff --git a/src/content/spec/security/cross-origin-isolation.md b/src/content/spec/security/cross-origin-isolation.md
index a101253a..a155ce8a 100644
--- a/src/content/spec/security/cross-origin-isolation.md
+++ b/src/content/spec/security/cross-origin-isolation.md
@@ -6,7 +6,7 @@ summary: "Three response headers — Cross-Origin-Opener-Policy, Cross-Origin-Em
status: recommended
order: 65
appliesTo: [all]
-relatedSlugs: [frame-ancestors, content-security-policy, permissions-policy, referrer-policy, reporting-endpoints]
+relatedSlugs: [frame-ancestors, content-security-policy, permissions-policy, referrer-policy, reporting-endpoints, fetch-metadata]
updated: "2026-06-11T00:00:00.000Z"
sources:
- title: "HTML Standard — Cross-Origin-Opener-Policy"
diff --git a/src/content/spec/security/fetch-metadata.md b/src/content/spec/security/fetch-metadata.md
new file mode 100644
index 00000000..bb2f9209
--- /dev/null
+++ b/src/content/spec/security/fetch-metadata.md
@@ -0,0 +1,104 @@
+---
+title: "Fetch Metadata request headers"
+slug: fetch-metadata
+category: security
+summary: "Browsers attach Sec-Fetch-Site, Sec-Fetch-Mode and Sec-Fetch-Dest to every request, describing where it came from and what it is for. A server that reads them can reject cross-site requests it never intended to serve, before any handler runs."
+status: recommended
+order: 63
+appliesTo: [all]
+relatedSlugs:
+ [
+ cookie-attributes,
+ frame-ancestors,
+ cross-origin-isolation,
+ x-content-type-options,
+ content-security-policy,
+ ]
+updated: "2026-09-04T00:00:00.000Z"
+sources:
+ - title: "Fetch Metadata Request Headers"
+ url: "https://www.w3.org/TR/fetch-metadata/"
+ publisher: "W3C Web Application Security Working Group"
+ - title: "Cross-Site Request Forgery Prevention Cheat Sheet — Fetch Metadata headers"
+ url: "https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html"
+ publisher: "OWASP"
+ - title: "MDN — Fetch metadata"
+ url: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Fetch_metadata"
+ publisher: "MDN"
+---
+
+## What it is
+
+Fetch Metadata is a set of request headers the browser attaches to every outgoing request, describing the context the request was made in. The server never has to ask for them and a page cannot forge them — the `Sec-` prefix makes them [forbidden request headers](https://fetch.spec.whatwg.org/#forbidden-request-header), so script cannot set or change them.
+
+Three of them carry the useful signal:
+
+- **`Sec-Fetch-Site`** — the relationship between the initiator and the target: `same-origin`, `same-site`, `cross-site`, or `none` (the user typed the URL or used a bookmark).
+- **`Sec-Fetch-Mode`** — how the request was made: `navigate`, `cors`, `no-cors`, `same-origin`, `websocket`.
+- **`Sec-Fetch-Dest`** — what the result will be used as: `document`, `image`, `script`, `style`, `iframe`, `empty`, and so on.
+
+A fourth, `Sec-Fetch-User`, is sent only on navigations triggered by real user activation. It is the odd one out: Safari has never shipped it, so a rule that requires it will misjudge every Safari visitor.
+
+```http
+GET /account/delete HTTP/1.1
+Sec-Fetch-Site: cross-site
+Sec-Fetch-Mode: no-cors
+Sec-Fetch-Dest: image
+```
+
+That request came from someone else's page, as an `
` tag, pointed at a state-changing endpoint. No legitimate use of your site produces it.
+
+**These are request headers you read, not response headers you set.** That is the point most people get backwards on first contact. Every other entry in this category — [CSP](/spec/security/content-security-policy/), [`frame-ancestors`](/spec/security/frame-ancestors/), [`X-Content-Type-Options`](/spec/security/x-content-type-options/) — is something you send and the browser enforces. Fetch Metadata inverts that: the browser sends, and **nothing happens unless your server acts on it**. Adding it to a headers config file does nothing at all.
+
+## Why it matters
+
+Cross-site attacks work by getting the visitor's own browser to make a request the visitor did not intend — a hidden form that posts to your `/settings` endpoint, an `
` whose `src` is your `/logout` URL, a `