fix(analytics): CSP-safe Clicky loader; Zod jitless under eval-less CSP - #164
Conversation
The deployed CSP restricts script-src to 'self' plus allowlisted origins,
so the inline clicky_site_ids initializer was blocked on every page load
and Clicky never received a site ID. Clicky's loader reads
document.currentScript.getAttribute("data-id") itself, so the ID now
rides on the async loader tag and no inline script is injected. Legacy
inline initializers are stripped unconditionally from served documents.
The deployed CSP has no 'unsafe-eval', so Zod's JIT fast path can never
activate; its cached allowsEval probe still called new Function("") once
per page load, which browsers surface as a securitypolicyviolation even
though Zod swallows the throw. Configuring jitless before any schema is
built skips the probe and keeps parsing on the interpreter path the CSP
already forces.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe change enables Zod jitless mode and updates Clicky analytics injection to use an asynchronous loader with a ChangesCSP compatibility
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR hardens the app against strict Content-Security-Policy (no inline scripts / no unsafe-eval) by making Clicky analytics initialization CSP-safe and configuring Zod v4 to avoid its eval/JIT probe path.
Changes:
- Replace the Clicky inline initializer with a CSP-safe loader
scripttag carrying the site ID viadata-id, and strip legacy inline initializers. - Add backend test coverage asserting the Clicky loader is injected with
data-idand without any inline initializer. - Configure Zod v4 in the canonical schemas module with
z.config({ jitless: true })to avoid CSPunsafe-evalviolations.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/main/java/com/williamcallahan/javachat/web/ClickyAnalyticsInjector.java | Switch Clicky initialization to a CSP-safe data-id loader pattern and remove legacy inline initializers. |
| src/test/java/com/williamcallahan/javachat/web/SeoControllerTest.java | Add regression test ensuring the Clicky loader is present with data-id and no inline initializer exists. |
| frontend/src/lib/validation/schemas.ts | Configure Zod v4 to run in jitless mode under eval-less CSP. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
|
|
||
| if (existingClickyLoader != null) { | ||
| existingClickyLoader.attr(CLICKY_SITE_ID_ATTRIBUTE, Long.toString(clickySiteId)); |
Fixes the two Content-Security-Policy violations found while dogfooding the PR #163 prod deployment.
Changes
var clicky_site_ids = ...push(<site-id>)as an inline script, whichscript-src 'self' ...blocks, so Clicky never received a site ID. The site ID now rides on the async loader tag'sdata-idattribute — Clicky's loader readsdocument.currentScript.getAttribute("data-id")itself (verified against https://static.getclicky.com/js). Legacy inline initializers are stripped from served documents unconditionally.'unsafe-eval', so Zod's JIT fast path can never activate; its cachedallowsEvalprobe still callednew Function("")once per load, surfacing asecuritypolicyviolation.z.config({ jitless: true })in the canonical schemas module skips the probe.Validation
make build(incl. Spotless) greenSeoControllerTestgreen, including newinjects_clicky_loader_without_inline_initializerasserting thedata-idloader and the absence of any inline initializernpm run validategreen; vitest 337/337