anomalyco / anomalyco/opencode

web: session delete silently no-ops on insecure origins (unguarded crypto.randomUUID)

Open
#48,144 1 comment 0 reactions 1 assignee View on GitHub

@Hona is already working on this.

Since Sep 9, 2026.

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

Description

Report an opencode Issue

Summary

Deleting a session in the web app silently fails when the UI is opened over plain HTTP on a non-localhost origin. The session store's remove() calls crypto.randomUUID() unguarded; crypto.randomUUID is undefined in insecure contexts, so the click handler throws synchronously before any request is sent — no network call, no error toast. The same unguarded secure-context-only crypto API pattern also breaks image attachments and several copy actions on insecure origins.

Environment

  • opencode version: 0.0.0-beta-19271
  • OS: Linux 7.0.14-orbstack (x64) — server in an OrbStack-managed container; web UI accessed from Chrome on macOS
  • Terminal: n/a (web app)
  • Shell: /usr/bin/zsh
  • Install/channel: npm beta (@opencode-ai/cli@beta, global install)
  • Active plugins: none

Reproduction

  1. Start the server: opencode2 serve --hostname 0.0.0.0 --port 58640
  2. Open the web app in Chrome over plain HTTP using a non-localhost hostname (e.g. http://<container-hostname>:58640) — an insecure context where crypto.randomUUID is unavailable
  3. Open any session's menu and click Delete, then confirm
  4. Nothing happens

Expected Behavior

The session is deleted (DELETE /api/session/{id}), or at minimum the "Failed to delete session" toast appears.

Actual Behavior

No request is sent; no toast appears. The browser console shows:

Uncaught (in promise) TypeError: crypto.randomUUID is not a function
    at Object.remove (runtime-*.js)
    at x (index-*.js)          // click handler
    at HTMLButtonElement.r [as $$click]

Additional Context

  • Regression vs beta-19086: the 19086 web bundle only references crypto.randomUUID inside a guarded helper (existence check + Math.random-based UUID fallback). beta-19271's session store remove() uses it raw to build the optimistic-update op id ({ id: crypto.randomUUID(), type: 'remove', sessionID }) even though a guarded helper exists in the same file.
  • Because the throw is synchronous, the caller's .catch (delete-failure toast) never attaches — hence a fully silent failure.
  • Workaround: access via http://localhost:<port> (secure context) or HTTPS; deletion works normally there. The server-side DELETE endpoint is unaffected.
  • Consistently reproducible on any insecure origin.
  • Same pattern, same version — other insecure-origin breakages found in the beta-19271 bundle:
    • Image attachments fail: the shared attach handler (paste/drop/picker) calls crypto.subtle.digest unguarded (crypto.subtle is also undefined in insecure contexts) and then builds the attachment with a raw crypto.randomUUID() id.
    • Several copy actions fail: multiple unguarded navigator.clipboard.writeText calls (copy path, copy session ID, text-field copy buttons, error-card copy). Only one site uses an execCommand fallback.
    • Guarded helpers with proper fallbacks exist in the same bundles (wd() for UUIDs, an execCommand clipboard fallback), so the fix pattern is already established in the codebase.

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.