anomalyco / anomalyco/opencode
web: session delete silently no-ops on insecure origins (unguarded crypto.randomUUID)
@Hona is already working on this.
Since Sep 9, 2026.
- 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
- Start the server:
opencode2 serve --hostname 0.0.0.0 --port 58640 - Open the web app in Chrome over plain HTTP using a non-localhost hostname (e.g.
http://<container-hostname>:58640) — an insecure context wherecrypto.randomUUIDis unavailable - Open any session's menu and click Delete, then confirm
- 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.randomUUIDinside a guarded helper (existence check +Math.random-based UUID fallback). beta-19271's session storeremove()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.digestunguarded (crypto.subtleis also undefined in insecure contexts) and then builds the attachment with a rawcrypto.randomUUID()id. - Several copy actions fail: multiple unguarded
navigator.clipboard.writeTextcalls (copy path, copy session ID, text-field copy buttons, error-card copy). Only one site uses anexecCommandfallback. - Guarded helpers with proper fallbacks exist in the same bundles (
wd()for UUIDs, anexecCommandclipboard fallback), so the fix pattern is already established in the codebase.
- Image attachments fail: the shared attach handler (paste/drop/picker) calls
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.