Skip to content

Send security headers: CSP, no framing, HSTS on HTTPS - #49

Merged
stretch0 merged 1 commit into
mainfrom
security-headers
Nov 2, 2026
Merged

stretch0 merged 1 commit into
mainfrom
security-headers

Conversation

@stretch0

@stretch0 stretch0 commented Nov 2, 2026

Copy link
Copy Markdown
Owner

Why

The Fly guide puts instances on the public internet, and openRun sent no security headers: any site could frame it (clickjacking), and nothing limited what scripts a page could run.

What changed

apps/api/src/security-headers.ts, using Hono's secureHeaders, on every response:

  • Content-Security-Policy: scripts from openRun only, plus the inline theme script in index.html allowed by its hash (read from the built page at startup, so editing the script can't break it). Images, fetches and workers from openRun, data:/blob: where needed (logo preview, MapLibre), and https://tile.openstreetmap.org. frame-ancestors 'none', object-src 'none', base-uri/form-action 'self'. Styles allow inline (react-easy-crop adds a <style> tag).
  • X-Frame-Options: DENY, plus Hono's defaults (nosniff, COOP/CORP same-origin and so on).
  • Strict-Transport-Security (one year) only when ORIGIN is HTTPS, so plain-HTTP local installs are unaffected.
  • Referrer-Policy: strict-origin-when-cross-origin, not Hono's no-referrer: OpenStreetMap's tile servers require a Referer, and this sends the origin, never the path.
  • Zod: its fast path probes new Function, which the policy blocks and the browser reports on every page. apps/web/src/zod-config.ts turns it off, imported first because Zod probes as each schema is created.

Checks

  • New tests: the theme script's hash is in the policy on the page and the API; framing denied; HSTS only over HTTPS.
  • A production build with sample data, in Chromium at phone size: the run page, stats, clubs, a club, a club run, club management and settings. No CSP violations, and the map tiles load and draw.
  • api and web lint, typecheck and tests pass; e2e: 12 passed.
  • Not checked: Safari/iOS, and push notifications with the headers on.

🤖 Generated with Claude Code

Every response now carries a Content-Security-Policy that allows only
openRun's own scripts (the inline theme script by hash) and OpenStreetMap
tiles, forbids framing (clickjacking), and on HTTPS asks browsers never to
use plain HTTP. The Referrer-Policy sends only the origin elsewhere, which
OpenStreetMap's tile servers require.

Zod's fast path probes eval, which the policy blocks, so the web app turns
it off before any schema is created.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@stretch0
stretch0 merged commit a5c5bba into main Nov 2, 2026
5 checks passed
@stretch0
stretch0 deleted the security-headers branch November 2, 2026 21:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant