Skip to content

fix: allow custom storage uploads through admin CSP#1979

Open
masonjames wants to merge 3 commits into
emdash-cms:mainfrom
masonjames:codex/fix-runtime-storage-csp
Open

fix: allow custom storage uploads through admin CSP#1979
masonjames wants to merge 3 commits into
emdash-cms:mainfrom
masonjames:codex/fix-runtime-storage-csp

Conversation

@masonjames

Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes direct browser uploads for custom S3-compatible storage adapters.

The admin CSP previously discovered upload origins only from a static storage descriptor or the built-in S3 adapter's S3_ENDPOINT. Runtime-resolved custom adapters could generate a valid signed upload URL, but connect-src 'self' blocked the browser's PUT before it reached storage.

This change falls back to the existing runtime getClientUploadOrigin() hook when the descriptor does not expose an endpoint. Explicit descriptor configuration and the built-in S3 environment fallback keep their current precedence.

Related issue: none; reproduced against a live custom-adapter deployment.

Type of change

  • Bug fix
  • Feature (requires maintainer-approved Discussion)
  • Refactor (no behavior change)
  • Translation
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm test passes (or targeted tests for my change)
  • pnpm format has been run
  • I have added/updated tests for my changes (if applicable)
  • User-visible strings in the admin UI are wrapped for translation (not applicable; no user-visible strings changed). Do not include messages.po changes except in translation PRs — a workflow extracts catalogs on merge to main.
  • I have added a changeset (if this PR changes a published package)
  • New features link to an approved Discussion: N/A — bug fix

AI-generated code disclosure

  • This PR includes AI-generated code — model/tool: OpenAI GPT-5 (Codex)

Screenshots / test output

No visual change.

  • pnpm build — passed
  • pnpm typecheck — passed
  • pnpm lint — passed
  • pnpm --filter emdash exec vitest run tests/unit/middleware/csp.test.ts — 19 passed
  • pnpm test — all core/admin/auth/cloudflare and other package tests passed; one unrelated existing Workerd integration test failed because two runner processes contended for hard-coded port 127.0.0.1:18788, including when rerun in isolation

@changeset-bot

changeset-bot Bot commented Jul 12, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 29fadd8

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
Name Type
emdash Patch
@emdash-cms/cloudflare Patch
@emdash-cms/sandbox-workerd Patch
@emdash-cms/fixture-perf-site Patch
@emdash-cms/perf-demo-site Patch
@emdash-cms/cache-demo-site Patch
@emdash-cms/do-demo-site Patch
@emdash-cms/do-solo-demo-site Patch
@emdash-cms/admin Patch
@emdash-cms/auth Patch
@emdash-cms/blocks Patch
@emdash-cms/gutenberg-to-portable-text Patch
@emdash-cms/x402 Patch
create-emdash Patch
@emdash-cms/auth-atproto Patch
@emdash-cms/plugin-embeds Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added query-count changed PR diff modifies query-count snapshot files area/core size/S review/needs-review No maintainer or bot review yet labels Jul 12, 2026
@github-actions

github-actions Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@pkg-pr-new

pkg-pr-new Bot commented Jul 12, 2026

Copy link
Copy Markdown

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@1979

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@1979

@emdash-cms/auth-atproto

npm i https://pkg.pr.new/@emdash-cms/auth-atproto@1979

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@1979

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@1979

@emdash-cms/contentful-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/contentful-to-portable-text@1979

emdash

npm i https://pkg.pr.new/emdash@1979

create-emdash

npm i https://pkg.pr.new/create-emdash@1979

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@1979

@emdash-cms/plugin-cli

npm i https://pkg.pr.new/@emdash-cms/plugin-cli@1979

@emdash-cms/plugin-types

npm i https://pkg.pr.new/@emdash-cms/plugin-types@1979

@emdash-cms/registry-client

npm i https://pkg.pr.new/@emdash-cms/registry-client@1979

@emdash-cms/registry-lexicons

npm i https://pkg.pr.new/@emdash-cms/registry-lexicons@1979

@emdash-cms/sandbox-workerd

npm i https://pkg.pr.new/@emdash-cms/sandbox-workerd@1979

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@1979

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@1979

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@1979

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@1979

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@1979

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@1979

@emdash-cms/plugin-field-kit

npm i https://pkg.pr.new/@emdash-cms/plugin-field-kit@1979

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@1979

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@1979

commit: 29fadd8

@emdashbot emdashbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review: fix runtime storage upload origin in admin CSP

The approach is sound and narrowly targeted: custom storage adapters that resolve their upload origin at runtime need a way to tell the admin CSP what to allow, since the descriptor and S3_ENDPOINT fallbacks are static. Falling back to a runtime hook after the existing precedence rules keeps the change additive and matches the architecture (runtime decisions live on emdash.storage, descriptor decisions live in config).

However, the PR introduces getClientUploadOrigin() as a runtime Storage contract but never adds it to the Storage interface in packages/core/src/storage/types.ts. The CSP helper is typed as Pick<Storage, "getClientUploadOrigin">, and context.locals.emdash.storage is typed as Storage | null. Since Storage currently has no such method, passing the runtime storage is a type-checked contract violation and custom adapters have no typed surface to implement. This is a real omission that blocks type-correct custom adapters.

The rest of the change is clean: precedence is respected (descriptor → S3_ENDPOINT → runtime), the new hook result is still run through getHttpOrigin() so malformed/non-HTTP origins are discarded, a reproducing unit test is added, the changeset is present, and no user-facing strings/SQL/content-table queries are involved.

Recommendation: add getClientUploadOrigin?(): string to the Storage interface, then this is good to go.

Comment thread packages/core/src/astro/middleware/csp.ts
@github-actions github-actions Bot added review/needs-rereview Author pushed changes since the last review and removed review/needs-review No maintainer or bot review yet labels Jul 12, 2026
@masonjames masonjames force-pushed the codex/fix-runtime-storage-csp branch from c08fb42 to c138d62 Compare July 12, 2026 14:17
@masonjames

Copy link
Copy Markdown
Contributor Author

recheck

@github-actions github-actions Bot removed the query-count changed PR diff modifies query-count snapshot files label Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/core cla: signed review/needs-rereview Author pushed changes since the last review size/S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant