feat: security headers on every response
The one real finding from reviewing the app before it goes public: HTML responses carried no security headers at all. Everything else held under attack — private repositories are 404 on every surface including /api, six injection attempts through the revision segment and four traversal spellings through the path all 404 with no execution, login throttles at ten attempts, raw .html and .svg come back as octet-stream with nosniff and a sandbox CSP, a filename containing a quote and a semicolon is sanitised before reaching a header, and the production cookie is __Host-session with Secure and HttpOnly. A layer, not a per-handler concern: a page added without these would simply not have them and nothing would fail. Steid renders no JavaScript at all — not a script tag on any page — so default-src 'none' is a policy this product can genuinely keep rather than aspire to. That is stricter than a typical CSP and worth defending on purpose: if a feature ever needs script, weakening it should be a decision rather than a quiet edit. 'unsafe-inline' is granted for styles only, and only because Topcoat's icon macro emits a vertical-align style attribute on every icon. Referrer-Policy is no-referrer rather than the usual strict-origin-when-cross-origin, because a private repository's URL contains its name and a README may link anywhere — the referrer would hand that name to whatever the visitor clicked. Headers use entry().or_insert(), never insert(): the raw-file endpoint sets its own stricter default-src 'none'; sandbox, and a blanket overwrite would quietly relax the one response that most needs locking down. Verified it survives. Also recorded: a near-miss where production appeared to serve an insecure cookie. It was a testing error — dotenvy reads .env from the working directory and the repo root has a dev one. The same trap applies in production, where the unit sets WorkingDirectory=/opt/steid. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JZwc7URWKVhkAuRTWiDmjA
JamesPatrickGill authored 1 day agoparentaa20db5Browse files
0f196544ea0591c71896899fc1289342b531f58c