2026-03-17 19:50:46Claude (MCP):
[mcp] Phase 1: expand security headers section with specific Caddy directives and CSP rationale
Plans/Rate_Limiting_And_Security_Headers.md ..
@@ 11,18 11,82 @@
## Phase 1: Security Headers (no module change)
-
Add to both `robot.wtf` and `*.robot.wtf` site blocks:
+
### Caddyfile snippet
+
+
Define a named snippet at the top of the Caddyfile (before any site blocks) and import it into the wiki site blocks. **Do not apply to the MCP site block** — MCP endpoints return JSON and the browser security headers are irrelevant there, and CSP in particular can cause unexpected behavior with SSE clients.
Omitting CSP (requires script audit), Referrer-Policy, Permissions-Policy (low priority). No `preload` on HSTS (permanent, hard to undo).
+
Apply it to the wiki site blocks:
+
+
```caddyfile
+
# Otterwiki web UI
+
wiki.robot.wtf {
+
import security_headers
+
import wiki_auth
+
reverse_proxy 3gw.lan:8080
+
}
+
+
# Auth, management UI (if served separately)
+
*.robot.wtf {
+
import security_headers
+
# ... other directives
+
}
+
```
+
+
**Do not import `security_headers` in the `mcp.robot.wtf` site block.**
+
+
### CSP rationale
+
+
Otterwiki's frontend (audited from templates): all JS and CSS are self-hosted (`/static/`). No external CDNs. MathJax, Mermaid, Font Awesome, and Roboto fonts are all bundled. However:
+
+
- `layout.html` has inline `<script>` blocks (flash message rendering) — requires `'unsafe-inline'` for scripts.
+
- `editor.html` has an inline `<style>` block — requires `'unsafe-inline'` for styles.
+
- `editor.js` uses `preview_block.innerHTML = data.preview_content` to render server-fetched HTML into the DOM — this is XSS-safe as long as the server sanitizes, but means wiki content may include `<img>` tags with arbitrary `https:` src URLs (user-uploaded or markdown-linked images). Hence `img-src 'self' data: blob: https:`.
+
- Font CSS uses local `data:` URIs for IE compat woff, so `font-src 'self' data:` is needed.
+
- `frame-ancestors 'none'` enforces no-iframe (equivalent to `X-Frame-Options: DENY` for modern browsers; keep both for compatibility).
+
+
Dropping `'unsafe-inline'` from `script-src` would require nonce injection in the app — that's an application change, out of scope for Phase 1.