Skip to content

fix(security): admit the platform asset origins the renderer emits - #3411

Closed
kwakayama wants to merge 3 commits into
mainfrom
fix/csp-platform-asset-origins
Closed

fix(security): admit the platform asset origins the renderer emits#3411
kwakayama wants to merge 3 commits into
mainfrom
fix/csp-platform-asset-origins

Conversation

@kwakayama

@kwakayama kwakayama commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

The default CSP forbade the assets the renderer itself emits. No hosted page hydrated, and every optimized image was blocked.

The contradiction

One response, sent by one server:

content-security-policy: ... script-src 'self' 'nonce-...'; img-src 'self' data: ...

and, in the body it was attached to:

origin the document references refs blocked by
images.veryfront.com 291 img-src 'self' data:
esm.sh (React, react-dom, jsx-runtime) 6 script-src 'self' 'nonce-...'

The renderer writes 291 URLs pointing at the platform's own image service, then sends a policy refusing that origin. React is imported from the ESM CDN by the framework's own hydration, then refused the same way. Browser console on production:

Loading the script 'https://esm.sh/react@19.2.4/jsx-runtime...' violates the following
Content Security Policy directive: "script-src 'self' 'nonce-...'"
Loading the image 'https://images.veryfront.com/imgproxy/...' violates ... "img-src 'self' data:"

This is framework-level. It affects every hosted project that renders an image or hydrates.

Fix

Platform-owned origins now live in one list, src/security/http/platform-asset-origins.ts, beside the existing HOSTED_STUDIO_ORIGINS that already feeds frame-ancestors. script-src and img-src consume it, so the policy and the emitters cannot drift apart silently.

Deliberately not widened

fonts.googleapis.com stays blocked. It is Google's origin, referenced by the project's layout, not platform infrastructure -- projects declare their own external origins through security.csp. Granting it by default would hand every hosted site an origin it never asked for.

connect-src, font-src, default-src, frame-src, media-src, worker-src: unchanged, and now explicitly asserted host-free.

The invariant is narrowed, not removed

default CSP admits no remote hosts or broad network schemes failed on this change with script-src must not hardcode a remote host. That stance could not hold -- it made the policy block its own response -- so it is rewritten to the property that does hold: nothing outside the platform allowlist gets in. The directives that gain nothing from a remote host are still pinned to exactly their old values.

A positive test pins the fix:

script-src remote hosts  ->  ["esm.sh"]
img-src remote hosts     ->  ["cdn.veryfront.com", "images.veryfront.com"]

Red before, green after.

Proof

Compiled binary, real production release, environment read off the live deployment:

script-src   'self' 'nonce-Ewxac6...' https://esm.sh
img-src      'self' data: https://images.veryfront.com https://cdn.veryfront.com
font-src     'self' data:      <- unchanged
connect-src  'self'            <- unchanged
default-src  'self'            <- unchanged

Suite: 431 passed / 5497 steps across security, modules, handlers, html, transforms. deno fmt clean.

Tradeoff worth reviewing

This permits scripts from esm.sh on every hosted page. That is a real widening, and I want it seen rather than buried. The cleaner long-term fix is serving React same-origin from /_vf_modules -- that path exists and works (/_vf_modules/_veryfront/react/runtime/core.js returns 200 once #3409 lands). Changing React delivery has caching and performance implications well beyond this defect, so this change matches the renderer's current behaviour instead of redesigning it. If you would rather close the gap by moving React same-origin, this PR is the wrong shape and I will write that one instead.

Related

Independent of #3409 (module pin conflict). I verified they are separate: with modules serving correctly, the document still carries all 6 esm.sh references. Both are needed for a hosted page to work.

Summary by CodeRabbit

  • Security
    • Updated production Content Security Policy settings to allow approved platform CDN scripts and image assets.
    • Maintained strict restrictions for other resource types and unapproved origins.
    • Added coverage confirming supported platform assets load correctly.

The default CSP was 'self'-only for scripts and images while the renderer
writes React from the ESM CDN and optimized image URLs from the platform
image service into every document it serves. The policy therefore forbade
the same response's own assets: no hosted page hydrated and every optimized
image was refused.

Platform origins now live in one list beside the existing Studio origin
allowlist, so the policy and the emitters cannot drift apart. Project-owned
external origins stay out -- those belong in project security.csp.
@kwakayama
kwakayama requested a review from kojiwakayama as a code owner August 6, 2026 06:06
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kwakayama, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 34 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a9cbf848-bc06-41e6-b13d-eb69dea897c5

📥 Commits

Reviewing files that changed from the base of the PR and between f6c4f50 and 5e4ce09.

📒 Files selected for processing (2)
  • docs/api-reference/veryfront/security.md
  • src/security/http/response/security-handler.test.ts
📝 Walkthrough

Walkthrough

The change adds shared platform asset origin constants and includes them in the default production CSP. Tests validate approved script and image origins while preserving restrictions on other CSP directives.

Changes

Platform asset CSP

Layer / File(s) Summary
Define platform asset origins
src/security/http/platform-asset-origins.ts
Adds platform image and CDN origin constants, plus grouped script, image, and combined asset origin lists.
Integrate origins into the default CSP
src/security/http/response/security-handler.ts, src/security/http/response/security-handler.test.ts
Adds platform script and image origins to the default CSP. Updates documentation and tests for the new allowlist behavior while retaining strict restrictions for connect-src, default-src, and frame-src.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: kojiwakayama

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: allowing renderer-emitted platform asset origins in the security policy.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/csp-platform-asset-origins

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/security/http/response/security-handler.test.ts`:
- Around line 314-327: Update the CSP assertions in the security-handler test to
explicitly verify that both media-src and worker-src contain no remote hosts,
alongside the existing host-free directive checks. Keep the platform allowlist
validation for applicable asset directives unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b427de33-c2b7-4dee-a71f-0e70f7214486

📥 Commits

Reviewing files that changed from the base of the PR and between e92fa11 and f6c4f50.

📒 Files selected for processing (3)
  • src/security/http/platform-asset-origins.ts
  • src/security/http/response/security-handler.test.ts
  • src/security/http/response/security-handler.ts

Comment thread src/security/http/response/security-handler.test.ts Outdated
The loop accepted a platform host in every directive it checked, so adding
one to media-src or worker-src would have passed. Only script-src and img-src
carry a platform asset; every other directive is now asserted exactly
host-free, and a directive added to the policy later is covered without
anyone remembering to list it.
deno task docs. The import and comments added to security-handler.ts moved
the exported declarations down a few lines, so the generated source links
went stale; no symbols changed.
@kwakayama
kwakayama enabled auto-merge August 6, 2026 06:28
@kwakayama
kwakayama added this pull request to the merge queue Aug 6, 2026
@kwakayama kwakayama mentioned this pull request Aug 6, 2026
@kwakayama
kwakayama removed this pull request from the merge queue due to a manual request Aug 6, 2026
@kwakayama

Copy link
Copy Markdown
Contributor Author

Superseded by #3417, which consolidates this with the other queued render-path fixes plus the v0.1.1206 bump so one queue pass lands the set.

Dequeued from the merge queue to avoid this merging underneath the consolidated branch and leaving it empty or conflicting. Please do not re-queue — merge #3417 instead. Closing once that lands.

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