Skip to content

UN-2238 [FIX] CSP: allow third-party origins found in report-only sweep - #2245

Open
Deepak-Kesavan wants to merge 1 commit into
mainfrom
UN-2238-csp-policy
Open

UN-2238 [FIX] CSP: allow third-party origins found in report-only sweep#2245
Deepak-Kesavan wants to merge 1 commit into
mainfrom
UN-2238-csp-policy

Conversation

@Deepak-Kesavan

Copy link
Copy Markdown
Contributor

What

  • Adds the third-party origins that the shipped frontend loads but the report-only CSP does not allow, so the report-only header reflects reality before it is switched to enforcing.
  • Drops the bare wss: wildcard from connect-src.
  • Adds .claude/skills/csp-check — scripts + procedure for re-checking the policy against a build or a running deployment.

Why

UN-2238. CSP is deployed in report-only mode; violations go to each user's browser console only, so gaps stay invisible until someone looks. This is that look, done against a live deployment (v0.176.0).

Two methods were used:

  1. Browsing while recording securitypolicyviolation across landing, dashboard, prompt studio (incl. PDF viewer), API/ETL/task, logs, users, LLM settings, platform settings, profile, manual review. One violation fired in normal use: ProductFruits' animations.css on style-src-elem.
  2. Per-directive probes against the live policy, for hosts the bundle references but whose code paths were not exercised (Monaco, emoji picker, LLMW pdf worker, GTM/GA4, Stripe, reCAPTCHA). Each host below was traced to a chunk in the deployed bundle.
Directive Added Loaded by
style-src cdn.jsdelivr.net, app.productfruits.com Monaco editor.main.css; ProductFruits CSS (observed)
font-src cdn.jsdelivr.net Monaco codicon.ttf
img-src cdn.jsdelivr.net, app.productfruits.com, cdn.productfruits.com, www.googletagmanager.com, www.google-analytics.com, www.google.com/recaptcha/, www.gstatic.com/recaptcha/, q.stripe.com emoji-datasource; ProductFruits media; GTM/GA pixels; reCAPTCHA assets; Stripe beacons
connect-src unpkg.com, api.productfruits.com, www.googletagmanager.com, region1.google-analytics.com, analytics.google.com, www.google.com/recaptcha/, m.stripe.network LLMW pdf worker; ProductFruits API; GA4 endpoints; reCAPTCHA api2; Stripe.js
frame-src www.googletagmanager.com, m.stripe.network react-gtm ns.html; Stripe.js
media-src new directive: 'self' blob: cdn.productfruits.com ProductFruits video (previously fell back to default-src 'self', no blob:)

How

  • One line changed in frontend/nginx.conf (the add_header Content-Security-Policy-Report-Only value), plus a comment on the wss: removal.
  • .gitignore un-ignores the new skill directory, matching the existing pattern for .claude/skills/worktree/.

Can this PR break any existing features. If yes, please list possible items. If no, please explain why.

No. The header stays -Report-Only, so nothing is blocked either way — the change only affects what gets reported. Every edit is additive except the wss: wildcard.

That removal is the one item worth a second pair of eyes: socket.io connects to window.location.origin (frontend/src/helpers/GetStaticData.jsgetBaseUrl), and 'self' covers same-origin ws/wss under CSP3. Verified by probing ws:// same-origin against a local nginx serving this exact policy — no violation reported. A deployment that terminates websockets on a different host or port would report (not block) it.

Database Migrations

  • None.

Env Config

  • None.

Relevant Docs

  • .claude/skills/csp-check/SKILL.md

Related Issues or PRs

Dependencies Versions

  • None.

Notes on Testing

  • docker run of nginx:alpine with this nginx.conf: config accepted, header emitted verbatim.
  • 48 per-directive probes against that local nginx: every origin the policy now lists loads without a report; 4 control probes to a disallowed host were all reported (so the policy is applied and still restrictive). The only entries flagged were https://hooks.stripe.com/ 404-redirecting to https://stripe.com — CSP evaluates redirect targets, not a real gap.
  • scan_origins.py --url against the deployment: every external host referenced by the 248 bundle chunks is now covered by some directive.

Sweep of the report-only policy on a live deployment (browsing + per-directive
probes) turned up hosts the shipped bundle loads but no directive allows:

- style-src/font-src: cdn.jsdelivr.net (Monaco CSS + codicon)
- img-src: cdn.jsdelivr.net (emoji-datasource), ProductFruits, GTM, GA,
  reCAPTCHA assets, q.stripe.com
- media-src: cdn.productfruits.com (new directive; default-src had no blob:)
- connect-src: unpkg.com, api.productfruits.com, GA4 regional endpoints,
  reCAPTCHA api2, m.stripe.network
- frame-src: googletagmanager ns.html, m.stripe.network

ProductFruits' animations.css was the one violation observed in normal use; the
rest belong to code paths and flows that were not exercised.

Drops the bare `wss:` wildcard: socket.io connects to window.location.origin
(GetStaticData getBaseUrl) and 'self' covers same-origin ws/wss per CSP3,
verified with a ws:// probe against nginx serving this policy.

Adds .claude/skills/csp-check so the policy can be re-checked against a build or
a deployment when a frontend dependency changes.
@github-actions

Copy link
Copy Markdown
Contributor

Frontend Lint Report (Biome)

All checks passed! No linting or formatting issues found.

@sonarqubecloud

Copy link
Copy Markdown

@greptile-apps

greptile-apps Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR expands the frontend’s report-only CSP to cover observed third-party resources, removes the unrestricted websocket source, and adds reusable CSP inspection tooling.

  • Adds directive-specific origins for ProductFruits, Monaco, analytics, reCAPTCHA, Stripe, and related media.
  • Adds scripts for extracting the nginx policy, scanning built or deployed bundles, and probing directives in a browser.
  • Documents the CSP verification procedure and exposes the new skill through .gitignore.

Confidence Score: 5/5

The PR appears safe to merge with no concrete blocking or independently actionable non-blocking issue identified.

The CSP remains report-only, the added origins align with the documented third-party resource types, and the removed websocket wildcard does not affect the current same-origin socket construction.

Important Files Changed

Filename Overview
frontend/nginx.conf Expands the report-only policy for known frontend resources and retains same-origin socket coverage through connect-src 'self'.
.claude/skills/csp-check/scripts/extract_policy.py Adds a focused parser for the single quoted nginx CSP header and supports human-readable and JSON output.
.claude/skills/csp-check/scripts/probe.js Adds directive-level browser probes with restrictive control requests and documented redirect interpretation.
.claude/skills/csp-check/scripts/scan_origins.py Adds a deliberately coarse host-presence scan for local Vite output or deployed chunks, with directive-level validation delegated to the probe.
.claude/skills/csp-check/SKILL.md Documents a layered static, probe, and real-usage procedure for validating the report-only CSP.
.gitignore Un-ignores the new CSP-check skill directory so its files are tracked.

Reviews (1): Last reviewed commit: "UN-2238 [FIX] CSP: allow third-party ori..." | Re-trigger Greptile

@github-actions

Copy link
Copy Markdown
Contributor

Unstract test results

Per-group results

Status Group Tier Passed Failed Errors Skipped Duration (s)
e2e-api-deployment e2e 3 0 0 0 16.6
e2e-coowners e2e 1 0 0 0 1.6
e2e-etl e2e 1 0 0 0 8.3
e2e-login e2e 2 0 0 0 1.2
e2e-prompt-studio e2e 1 0 0 0 4.6
e2e-smoke e2e 2 0 0 0 2.5
e2e-workflow e2e 1 0 0 0 16.7
integration-backend integration 267 0 0 26 44.8
integration-connectors integration 1 0 0 7 7.9
integration-workers integration 140 0 0 1 48.1
unit-backend unit 998 0 0 1 40.0
unit-connectors unit 63 0 0 0 10.2
unit-core unit 33 0 0 0 1.4
unit-platform-service unit 15 0 0 0 2.7
unit-rig unit 117 0 0 0 5.6
unit-sdk1 unit 518 0 0 0 22.7
unit-workers unit 1346 0 0 1 104.2
TOTAL 3509 0 0 36 339.0

Critical paths

⚠️ Critical paths not yet covered

  • workflow-execution-fan-out — Multi-file workflow execution fans out to file-processing workers and rejoins. (declared coverage: no groups declared)
✅ Covered critical paths
  • auth-login — covered by e2e-login
  • adapter-register-llm — covered by integration-backend
  • workflow-author — covered by integration-backend
  • co-owner-manage — covered by integration-backend, e2e-coowners
  • workflow-create-execute — covered by e2e-workflow
  • api-deployment-provision — covered by integration-backend
  • api-deployment-auth — covered by integration-backend
  • api-deployment-run — covered by e2e-api-deployment
  • mcp-server-auth — covered by integration-backend
  • mcp-platform-auth — covered by integration-backend
  • prompt-studio-author — covered by integration-backend
  • prompt-studio-fetch-response — covered by e2e-prompt-studio
  • connector-register-test — covered by integration-backend
  • pipeline-etl-execute — covered by e2e-etl
  • usage-aggregate-read — covered by integration-backend
  • usage-token-tracking — covered by e2e-api-deployment
  • callback-result-delivery — covered by e2e-api-deployment

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