Skip to content

fix(opencode): allow blob URLs in the app CSP for image attachments - #140

Merged
jeonghun-jj-lee merged 1 commit into
local/amicodefrom
fix/image-attachments
Aug 8, 2026
Merged

fix(opencode): allow blob URLs in the app CSP for image attachments#140
jeonghun-jj-lee merged 1 commit into
local/amicodefrom
fix/image-attachments

Conversation

@gennadiryan

@gennadiryan gennadiryan commented Aug 8, 2026

Copy link
Copy Markdown
Member

Important

Problem

Image attachments inside the Amicode webview were unusable: a pasted screenshot staged a broken thumbnail, and sending with a staged image failed ("Failed to send prompt / failed to fetch"), stalling the chat until the image was removed. Text-only messages were unaffected.

Approach

Allow the blob scheme in the app server's shared Content-Security-Policy for the image, connection, and media source lists. The attachment pipeline stages thumbnails and sends payloads entirely through object URLs, and the policy omitted the one scheme those URLs use — so the display path and the send path failed for the same single reason.

Approaches Considered

  • Allow blob in the app policy (chosen) — one policy change; restores thumbnails and sending together, for every attachment source.
  • Remove object URLs from the pipeline (render and send via data URLs) — larger change, and it would still leave the policy hostile to future blob use; retained as a second pass if the first proves insufficient.
  • Relax the policy wholesale — rejected: only one scheme was missing, and it is same-origin and page-created.

Scope

  • In: the app server's shared policy (image, connection, media sources) and its assertion coverage; verification across clipboard screenshots, copied files, and the attachment picker.
  • Out: the clipboard bridge and paste ownership — settled separately and unrelated to this defect; the accepted-format allowlist and absent size cap — deferred; the widget-frame policy — a separate surface carrying the same omission, deliberately not bundled.

Assumptions / Open Qs

  • The diagnosis is confirmed by the two policy refusals (image and connection) the failing pipeline surfaces in the console.
  • Whether the widget-frame surface needs the same allowance is unresolved.

What was failing

The shared policy listed network schemes and the data scheme but not the blob scheme: img-src 'self' data: https:, media-src 'self' data:, connect-src * data:. The wildcard matches network schemes only; non-network schemes must be listed explicitly, which is why data: was already there and blob: was not. Every attachment thumbnail is an object URL (image directive), and every send encodes the staged blob by fetching its object URL (connection directive) — both refused, hence the broken thumbnail and the failed send.

What changed

  • The shared policy's image, media, and connection source lists now include the blob scheme. Nothing else in the policy changes.
  • The connection-source entry is appended after the existing data entry, and the policy assertion coverage now checks the blob entries explicitly.

Verification

  • App server policy tests: passing, including the explicit blob-scheme assertions.
  • Paste regression suite (global-clipboard): passing — the single-value paste behavior (one keystroke, one insert, with and without shift) is unchanged.
  • Typecheck: clean for the touched packages; the remaining repo-level typecheck errors are pre-existing (missing generated SDK modules, confirmed against the pre-change baseline).
  • Remote GUI retest: the attachment button works; a screenshot pasted via the paste key stages into the attachments set; copy/paste shows no regression. The retested binary is the stamped build attributable to this change.

Key Decisions

  • Scheme-scoped allowance, nothing else: only the three source lists change.
  • Media included although the report concerns images — the pipeline is shared, and the same omission breaks audio and video attachments identically.
  • Object URLs stay. Replacing them is viable hardening but not required to fix the defect, and would enlarge the change under verification.

Constraints & Invariants

  • The blob scheme is same-origin and page-created; no remote origin is added to any source list.
  • No change to the clipboard bridge protocol, its message kinds, or paste ownership.
  • No change to the widget-frame policy or to the host webview policy.

Source

Companion to harmoniqs/opencode#261 (image-pasting failure). Unrelated to PR #130 (copy/paste duplication fix) — different mechanism, fix, and verification; the addendum issue #141 records the distinction. Related seam work: harmoniqs/amicode#243. Design of record: notes/image-attachment-csp.md in the harness.

Notes

The defect's diagnosis was pinned by source-independence: identical symptoms for screenshots, copied files, and picker attachments meant the fault sat in the shared pipeline or its policy — downstream of every paste path. Earlier tool versions fail the same way, consistent with a policy that predates the paste work.

@jeonghun-jj-lee
jeonghun-jj-lee merged commit 28ec2a0 into local/amicode Aug 8, 2026
1 of 4 checks passed
@jeonghun-jj-lee
jeonghun-jj-lee deleted the fix/image-attachments branch August 8, 2026 06:10
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.

2 participants