Skip to content

feat: add a Content-Security-Policy to the page routes - #106

Merged
cletqui merged 1 commit into
mainfrom
petithub-csp
Sep 2, 2026
Merged

cletqui merged 1 commit into
mainfrom
petithub-csp

Conversation

@cletqui

@cletqui cletqui commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Follow-up A from the review. Stacked on #105 — GitHub will retarget this to main once #105 merges.

New pageCsp middleware (src/utils/headers.tsx) applied only to / and /template, so the JSON API and the CDN-backed Swagger UI are untouched.

default-src 'self';
script-src 'self' 'nonce-<per-request>';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https://avatars.githubusercontent.com https://*.githubusercontent.com;
connect-src 'self'; manifest-src 'self';
base-uri 'none'; object-src 'none';
form-action 'self' https://github.com; frame-ancestors 'none'
  • Nonce for streaming: hono's stream: true Suspense emits ~4 inline hydration <script> tags. A per-request nonce is generated in pageCsp, stashed on c.var.cspNonce, and threaded into those scripts via <StreamingContext.Provider value={{ scriptNonce }}> in renderer.tsx. Verified locally: the header nonce and every streamed <script nonce="…"> match within a request; zero un-nonced inline scripts.
  • style-src 'unsafe-inline' stays — the language-dot colour is a dynamic style attribute and style attributes can't carry a nonce. Low risk (all rendered strings are hono-escaped; no HTML-injection surface).
  • /static/script.js is src-based, allowed by script-src 'self'.

tsc clean, build OK (484 kB), wrangler pages dev dist boots; / and /template carry the CSP, /api and /api/swagger do not.

Needs a real browser pass before merge (I can't do this offline): open the preview with the devtools console and confirm — repo renders and streams in, avatars load, /api/swagger still works, and there are no CSP violation errors. Tell me what to loosen if anything breaks.

New per-route `pageCsp` middleware on `/` and `/template` only — the JSON API
and the CDN-backed Swagger UI are left untouched.

script-src is 'self' + a per-request nonce; the nonce is threaded into hono's
streaming Suspense hydration scripts via StreamingContext so a strict policy
doesn't freeze the page on the loader. style-src keeps 'unsafe-inline' for the
dynamic language-dot colour (style attributes can't carry a nonce).
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying petithub with  Cloudflare Pages  Cloudflare Pages

Latest commit: 89fd657
Status: ✅  Deploy successful!
Preview URL: https://b4b66d11.petithub.pages.dev
Branch Preview URL: https://petithub-csp.petithub.pages.dev

View logs

Base automatically changed from petithub-slim-octokit to main September 2, 2026 11:19
@cletqui
cletqui merged commit c440c27 into main Sep 2, 2026
2 checks passed
@cletqui
cletqui deleted the petithub-csp branch September 2, 2026 11:20
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