fix(csp): close report-only allowlist gaps for OneSignal, RPC and analytics - #2479
Conversation
…lytics The first hours of report-only traffic produced ~800 violations, so the policy would break real functionality if promoted to enforcing as-is. Audited every reported host against the code that originates it: - OneSignal (cdn/api) was absent entirely — enforcing would stop the web SDK from loading and take web push with it - chain RPC endpoints: allowlist both sources, the curated rpcUrls in general.consts.ts and viem's per-chain defaults that wagmi's bare http() transports fall back to for external-wallet flows - GA4's region-specific beacon host and GTM's doubleclick/google.com pings, which the deliberately-installed GTM tag emits - ipapi.co (useGeoLocation), api.justaname.id (JustaName provider), and storage.crisp.chat via a *.crisp.chat widening Stays report-only; promotion waits until the stream is quiet.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThe Next.js report-only CSP configuration centralizes chain RPC hosts and expands ChangesCSP allowlist expansion
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Code-analysis diffPainscore total: 6247.08 → 6247.08 (0) |
🧪 UI test report — ✅ all greenSuites
📊 Coverage (unit)
⏱ 10 slowest test cases
|
kushagrasarathe
left a comment
There was a problem hiding this comment.
Reviewed — SAFE. Approving.
CSP allowlist gaps closed for legitimate OneSignal / Google Analytics origins, still in report-only mode — no enforcement change, no unsafe-* widening. Low risk.
No blocking issues.
Follow-up to #2462. In the first hours after that merged, the report-only policy produced ~800 violations (Sentry
logger:csp). Nothing is broken today — disposition isreport— but promoting this policy to enforcing as-is would break real functionality.I audited every reported host against the code that actually originates the request.
OneSignal was missing entirely
cdn.onesignal.com(24 hits,script-src-elem) is the web SDK loader, andapi.onesignal.comwas blocked under bothscript-src-elem(12) andconnect-src(6). Enforcing would have stopped the SDK from loading at all and taken web push with it. Added the two hosts explicitly toscript-src(kept tight, since that's the XSS-relevant directive) andhttps://*.onesignal.comtoconnect-src.Chain RPC endpoints — both sources, not just the reported ones
The reported RPC hosts (~780 of the 800 violations) are only half the story. There are two independent sources and both need allowlisting:
rpcUrlsinsrc/constants/general.consts.ts— the curated per-chain list our own viem clients use.http()with no URL, so external-wallet flows fall back to viem's built-in RPC per chain.Source 2 hadn't shown up in the reports yet (those flows are rarer), so allowlisting only what was reported would have meant a second round of violations. I enumerated both, which is why the list includes hosts like
eth.merkle.ioandrpc.gnosischain.comthat aren't in the Sentry data.Provider-level wildcards (
*.core.chainstack.com,*.publicnode.com,*.arbitrum.io,*.drpc.org) because each provider serves one subdomain per network; single-host providers are listed exactly. Noted in the "known-loose parts" comment as something to revisit before promotion.The list is a hand-kept mirror —
next.config.jsis CommonJS andgeneral.consts.tsis TS, so neither source is importable here. There's a comment on the constant saying to re-check it when either source gains a chain.Analytics
analytics.google.com(50),region1.analytics.google.com(29),stats.g.doubleclick.net(16),www.google.com(15). These are GA4's region-specific beacon and GTM's audience/conversion pings — the marketing analytics stack depends on them, so they're allowlisted to keep reporting intact once the policy is enforcing.Remaining app traffic
ipapi.co(useGeoLocation),api.justaname.id(JustaName ENS provider), andstorage.crisp.chat— the last via wideningclient.crisp.chatto*.crisp.chat, since Crisp serves assets from several subdomains.Verification
next.config.jsloads,eslintclean,prettierreports unchangedSummary by CodeRabbit