fix(security): Add security headers and harden external link rendering - #13
fix(security): Add security headers and harden external link rendering#13euxaristia wants to merge 2 commits into
Conversation
vercel.json had no Content-Security-Policy, X-Frame-Options, HSTS, Referrer-Policy, or Permissions-Policy, leaving the site framable and CSP-less as a backstop against markdown/link injection. PeerList, ClonePanel, and HomePage also rendered peer.http_url and clone_url (both sourced from the gossip network / node API, not this app) directly into <a href>, which React does not scheme-filter the way DOMPurify does for the markdown pipeline — a javascript: URL from a malicious peer would have executed on click.
bun update within existing semver ranges. Fixes advisories in dompurify (XSS via detached-subtree hook removal, the markdown pipeline's sanitizer), react-router-dom (open redirect, protocol-validation XSS, inefficient-route-matching DoS), postcss, and nanoid. Not fixed here: sharp (via @vercel/og, server-side OG image generation) and undici (via jsdom, test-only) both need a breaking major-version bump outside this update's semver ranges.
|
@coderabbitai full review |
|
The One thing that supports merging, since it's the first objection I'd expect someone to raise: the CSP does not break syntax highlighting. Two maintenance footguns worth a comment in the code, because both fail silently and neither is obvious six months from now: 1. The sha256 pin and the inline theme script are now coupled. 2. Neither blocks merging. |
Summary
vercel.jsonjavascript:/other unsafe URL schemes before rendering peer/repo URLs as<a href>, since those values come from the gossip network and node API, not this appChanges
vercel.json: adds aheadersblock applying CSP,X-Frame-Options: DENY,X-Content-Type-Options: nosniff,Referrer-Policy,Permissions-Policy, and HSTS to every route.script-srcallows'self'plus a sha256 hash for the one inline anti-FOUC theme script inindex.html;style-srckeeps'unsafe-inline'for React's inlinestyleattributes and Google Fonts.index.html: comment noting that editing the inline theme script requires recomputing its CSP hash, or it silently stops running.src/lib/api.ts: newisHttpUrl()guard.src/components/peers/PeerList.tsx:peer.http_url(fromGET /api/v1/peers, i.e. other nodes on the gossip network) now only renders as a link when it'shttp(s); otherwise falls back to plain text. React doesn't scheme-filterhrefthe way the DOMPurify-based markdown pipeline does for links.src/components/repo-detail/ClonePanel.tsx,src/pages/HomePage.tsx: same guard onclone_urlbefore rendering the "clone over https" link.bun.lock,package.json:bun update(semver-respecting). Notablydompurify3.4.11 → 3.4.14 andreact-router-dom7.17.0 → 7.18.2, both of which had open advisories.Not included:
sharp(via@vercel/og, used for OG image generation) andundici(viajsdom, test-only) both need a breaking major-version bump to clear their advisories — out of scope for a semver update.Test plan
bun run lintbun run test— 158 passedbun run build— typecheck + production build succeeddist/index.html's inline theme script still matches the CSPsha256-hashbun audit— dompurify, react-router-dom, postcss, nanoid advisories cleared; sharp and undici remain (documented above)