Skip to content

Enforce the strict web CSP (was report-only) - #7

Merged
sparkyfen merged 2 commits into
consfyi:mainfrom
sparkyfen:security/web-csp-enforce
Jul 17, 2026
Merged

Enforce the strict web CSP (was report-only)#7
sparkyfen merged 2 commits into
consfyi:mainfrom
sparkyfen:security/web-csp-enforce

Conversation

@sparkyfen

Copy link
Copy Markdown
Contributor

Promotes the strict CSP from report-only to enforced, following #6.

Since #6 merged, the strict policy ran as Content-Security-Policy-Report-Only and was validated against real traffic:

  • Headless sweep of the public routes (list/detail/map/calendar/search): zero app violations.
  • An authenticated Bluesky login (OAuth + session): zero violations.
  • The only report-only violation anywhere was Cloudflare's own Web Analytics beacon (static.cloudflareinsights.com), external to app code.

This PR:

  • postbuild now replaces the enforced Content-Security-Policy with the full strict policy (script-src 'self' + the inline-bootstrap-script sha256 hashes, plus scoped style/img/connect/font/worker directives) instead of adding a report-only header.
  • Allowlists https://static.cloudflareinsights.com in script-src so the analytics beacon isn't blocked (its data POST is already covered by connect-src https:).
  • The committed public/_headers keeps the safe tier as a fallback if the build step is ever skipped — never a broken CSP.

Re-verified the enforced build under wrangler pages dev: single enforced header, zero securitypolicyviolation events across list/detail/map/calendar, app fully functional (Mantine, maplibre tiles/fonts/sprites, data.cons.fyi fetches all 200).

Promotes the strict policy from Content-Security-Policy-Report-Only to the
enforced Content-Security-Policy: postbuild now REPLACES the safe-tier CSP
line with the full policy (script-src pinned to inline-script hashes + scoped
resource directives) instead of adding a report-only header.

Validated in report-only against real traffic first: a headless public-route
sweep and an authenticated Bluesky login both came back clean; the only
report-only violation was Cloudflare's own Web Analytics beacon, now
allowlisted via https://static.cloudflareinsights.com in script-src (its data
POST is covered by connect-src https:).

Follow-up to security review 2026-07-14 finding consfyi#3.
Addresses the PR#7 review:
- The inline-script lookahead now requires whitespace before src= (\ssrc=
  not \bsrc=), so a data-src / *-src attribute isn't mistaken for a real src
  and skipped — a skipped inline script has no hash and would be blocked once
  the CSP is enforced.
- The _headers rewrite uses a function replacement so a $ in the policy can't
  be read as a String.replace token.
- New scripts/inject-csp.test.ts runs the real postbuild against throwaway
  build/client fixtures: inline scripts hashed, external src excluded, data-src
  not misclassified, enforced (no report-only) with indentation preserved, and
  aborts when no inline script is found. vitest include broadened to scripts/.
@sparkyfen
sparkyfen merged commit 312cdec into consfyi:main Jul 17, 2026
1 check passed
@sparkyfen
sparkyfen deleted the security/web-csp-enforce branch July 17, 2026 08:56
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