anomalyco / anomalyco/opencode

[Bug] Web UI CSP blocks `blob:` URLs — dragging an image into chat fails with "NetworkError when attempting to fetch resource"

Open
#40,814 2 comments 0 reactions 1 assignee View on GitHub

@Brendonovich is already working on this.

Since Aug 6, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Description

Environment

  • opencode version: 1.18.12 (npm install -g opencode-ai, opencode-windows-x64)
  • OS: Windows 10/11
  • Browser: Firefox (error message "NetworkError when attempting to fetch resource" is Firefox-specific; Chrome shows "Failed to fetch")
  • Setup: opencode web, accessed at http://localhost:4096

Description

Dragging an image into the web chat input and sending it always fails. The message never reaches the server (no message=process entry appears in the server log for the failed attempt), so the failure is entirely client-side.

Browser console shows the real cause — the server's own Content-Security-Policy blocks the blob: URLs the web client uses to read back the dropped image:

Content-Security-Policy: ... blocked loading ... blob:http://localhost:4096/<uuid> (connect-src)
Content-Security-Policy: ... blocked loading ... blob:http://localhost:4096/<uuid> (img-src)

The CSP header is served by the opencode server itself for the web UI (HEAD / response):

Content-Security-Policy: default-src 'self'; script-src 'self' 'wasm-unsafe-eval' 'sha256-...';
  style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:;
  media-src 'self' data:; connect-src * data:

Neither img-src nor connect-src includes blob:. Per the CSP spec, the * wildcard does not match the blob: scheme, so:

  • fetch(blob.url) → blocked by connect-src → throws NetworkError
  • <img src="blob:..."> previews → blocked by img-src

Steps to reproduce

  1. Run opencode web and open http://localhost:4096 in Firefox.
  2. Drag an image file into the chat input.
  3. Send the message.
  4. Toast shows "Failed to send prompt"; console shows the CSP violations above.

Expected behavior

Images dropped into the web chat are base64-encoded and sent to the server (or otherwise processed), as designed.

Root cause analysis

The web client (packages/app) stores dropped images in IndexedDB and references them via URL.createObjectURL(blob) (packages/app/src/utils/draft-store.ts). On send, blobDataUrl() first does fetch(blob.url) to read the blob back into a base64 data URL (draft-store.ts), then posts it inline in the JSON body of POST /session/{id}/prompt_async (packages/app/src/components/prompt-input/submit.ts).

That fetch(blob.url) on a blob: URL is blocked by the server's CSP connect-src * data: directive, producing the NetworkError. The failing request therefore never reaches the server. The same CSP also blocks inline <img> previews of blob: URLs via img-src.

There is no separate image-upload endpoint; images are embedded inline as base64, so the blob: fetch step is on the critical path for every image attachment in the web UI.

Suggested fix

Include blob: in the CSP directives, e.g.:

img-src 'self' data: blob: https:;
connect-src * data: blob:

(or the minimum required: img-src and connect-src must allow blob:).

Longer term, moving attachments to a dedicated upload endpoint (write blob server-side, reference by ID) would also avoid inlining multi-MB base64 into a single JSON POST, but the CSP fix alone resolves this specific failure.

Workarounds (current)

  • Attach the image by its file path via @C:\path\image.png in the input (server reads the file directly; avoids blob: fetch).
  • Use the TUI (opencode) which is not affected by the browser CSP.

Logs

  • Server log (~/.local/share/opencode/log/opencode.log): no entries for the failed send — confirms the request never reached the server.
Plugins

No response

OpenCode version

No response

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

No response

Terminal

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.