Skip to content

fix(ui): use feature detection for crypto.randomUUID to support HTTP deployments - #1868

Merged
EItanya merged 5 commits into
kagent-dev:mainfrom
wsszh:fix/crypto-randomuuid-insecure-context
May 27, 2026
Merged

EItanya merged 5 commits into
kagent-dev:mainfrom
wsszh:fix/crypto-randomuuid-insecure-context

Conversation

@wsszh

@wsszh wsszh commented May 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • The UI uses crypto.randomUUID() which requires a Secure Context (HTTPS or localhost). Deployments served over plain HTTP crash on /agents/new with Uncaught TypeError: crypto.randomUUID is not a function.
  • Introduces a generateId() utility in ui/src/lib/utils.ts that detects crypto.randomUUID availability at runtime and falls back to the uuid package (already a dependency, v14) when unavailable.
  • Replaces all 8 crypto.randomUUID() call sites across 4 source files.

Changes

File Change
ui/src/lib/utils.ts Add generateId() with runtime feature detection
ui/src/lib/promptSourceRow.ts crypto.randomUUID() → generateId()
ui/src/lib/openClawSandboxForm.ts crypto.randomUUID() → generateId()
ui/src/components/prompts/FragmentEntriesEditor.tsx 4× crypto.randomUUID() → generateId()
ui/src/app/agents/new/page.tsx 2× crypto.randomUUID() → generateId()

Context

crypto.randomUUID() is a Web Crypto API gated behind Secure Context. Any deployment accessed via http:// (common in internal/dev clusters without TLS termination) crashes when rendering the agent creation form. The uuid npm package (v14, already in package.json) uses crypto.getRandomValues() which works in all contexts.

The fix uses runtime feature detection (typeof crypto.randomUUID === "function") so it works with the pre-built Docker image regardless of deployment configuration — no Helm or environment variable changes needed.

ui/public/mockServiceWorker.js also calls crypto.randomUUID() but is auto-generated by MSW and runs in a Service Worker context (always secure), so it is not modified.

Test plan

  • cd ui && npm run build passes
  • cd ui && npm run lint passes
  • Deploy over HTTP → /agents/new → "Skip wizard" → form loads without crash
  • Deploy over HTTPS → same flow works using native crypto.randomUUID()
  • grep -r 'crypto.randomUUID' ui/src/ returns only utils.ts feature-detection branch (and mockServiceWorker.js)

…deployments

crypto.randomUUID() requires a Secure Context (HTTPS or localhost).
Deployments served over plain HTTP crash on /agents/new with
"Uncaught TypeError: crypto.randomUUID is not a function".

Add a generateId() utility that detects crypto.randomUUID availability
at runtime and falls back to the uuid package (already a dependency)
when unavailable. Replace all 8 crypto.randomUUID() call sites.

Signed-off-by: wsszh <[email protected]>
Signed-off-by: sup <[email protected]>
Copilot AI review requested due to automatic review settings May 14, 2026 08:19
@wsszh
wsszh requested a review from peterj as a code owner May 14, 2026 08:19
@github-actions github-actions Bot added the bug Something isn't working label May 14, 2026

Copilot AI 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.

Pull request overview

Fixes a runtime crash on HTTP deployments where crypto.randomUUID() is unavailable outside Secure Contexts. Adds a generateId() helper with feature detection that falls back to the uuid package, and replaces all call sites.

Changes:

  • Add generateId() utility in ui/src/lib/utils.ts with runtime feature detection and uuid v4 fallback.
  • Replace all 8 crypto.randomUUID() call sites in 4 files with generateId().

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
ui/src/lib/utils.ts Adds generateId() helper and imports uuidv4 fallback.
ui/src/lib/promptSourceRow.ts Switches to generateId() for prompt source row ids.
ui/src/lib/openClawSandboxForm.ts Switches to generateId() for sandbox channel row ids.
ui/src/components/prompts/FragmentEntriesEditor.tsx Switches 4 call sites to generateId() for fragment row ids.
ui/src/app/agents/new/page.tsx Switches 2 call sites to generateId() for prompt source row ids.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@EItanya
EItanya merged commit e9d43f6 into kagent-dev:main May 27, 2026
75 of 119 checks passed
Charlesthebird added a commit that referenced this pull request Sep 17, 2026
`crypto.randomUUID` was fixed once in #1868 and came back when the interface was
rewritten and the file holding the helper went with it. A note in a file is lost
the same way twice, so the rule states it where a rewrite cannot drop it, and
names the helper to use instead. `navigator.clipboard` is listed for the same
reason: bare, it fails silently rather than loudly.

Signed-off-by: Nicholas Bucher <[email protected]>
krisztianfekete pushed a commit to krisztianfekete/kagent that referenced this pull request Sep 17, 2026
…ries (kagent-dev#2865)

---
*🤖 written by Claude (start)*

## Changelog

The UI now works when served over plain http from anything but
localhost, and one component throwing no longer blanks the page.

## Testing

1. `cd ui && yarn dev --host`, then open the printed **Network** URL — a
LAN IP, not localhost, so not a secure context.
2. `/schedules/new` loads and takes input. On `main` it throws
`crypto.randomUUID is not a function` at mount and stays blank.
3. Share a conversation and press **Copy link**. The button reports
whether it worked; on `main` it silently does nothing here.
4. Put `crypto.randomUUID()` back in `ScheduledRunForm.tsx` and reload.
The error renders inside the shell, nav usable, stack behind **Error
details**.

## Additional Notes

This reinstates kagent-dev#1868, which fixed the same crash in May. That fix lived
in `ui/src/lib/utils.ts` and went with the interface rewrite. The lint
rule is the part meant to outlast the next one.

`randomId()` returns a v4 UUID because the control plane validates some
of these ids as UUIDs. It uses `crypto.getRandomValues`, which carries
no secure-context condition.

The clipboard fallback answers the document's own `copy` event, as antd
does. antd's `copyable` UI is not used: it reports a copy whatever
`copy()` returns.

Not covered: a module that throws while being evaluated. `main.tsx`
never runs, so no boundary exists yet.

---
*🤖 written by Claude (end)*

---------

Signed-off-by: Nicholas Bucher <[email protected]>
Charlesthebird added a commit that referenced this pull request Sep 21, 2026
---
*🤖 written by Claude (start)*

## Changelog

Copy buttons work on deployments served over plain http, and say so when
a copy fails.

## Testing

1. `cd ui && npm run dev`, then open the app on a LAN IP rather than
localhost — that origin is not a secure context, so
`navigator.clipboard` is undefined.
2. Expand a tool result and press copy. The tick appears and the
clipboard holds the result; before, nothing happened and nothing was
said.
3. Copy a code block, the LLM-call JSON, and a share link. Each reports
its outcome.

## Additional Notes

This is the other half of #1868, which fixed `crypto.randomUUID` for
these deployments and left the clipboard alone. That fix is already here
and needs no change.

`copyText` answers the document's own `copy` event rather than selecting
a borrowed textarea. Nothing needs focus, so it also works inside a
dialog that traps it — the share dialog's old fallback appended its
textarea to `document.body` and copied nothing there while reporting
success.

Success is the event having fired, not what `execCommand` returns: it
returns true for copying nothing.

---
*🤖 written by Claude (end)*

Signed-off-by: Nicholas Bucher <[email protected]>
Co-authored-by: Eitan Yarmush <[email protected]>
alexdarbyshire pushed a commit to alexdarbyshire/kagent that referenced this pull request Oct 5, 2026
…ries (kagent-dev#2865)

Signed-off-by: alexdarbyshire <[email protected]>

---
*🤖 written by Claude (start)*

## Changelog

The UI now works when served over plain http from anything but
localhost, and one component throwing no longer blanks the page.

## Testing

1. `cd ui && yarn dev --host`, then open the printed **Network** URL — a
LAN IP, not localhost, so not a secure context.
2. `/schedules/new` loads and takes input. On `main` it throws
`crypto.randomUUID is not a function` at mount and stays blank.
3. Share a conversation and press **Copy link**. The button reports
whether it worked; on `main` it silently does nothing here.
4. Put `crypto.randomUUID()` back in `ScheduledRunForm.tsx` and reload.
The error renders inside the shell, nav usable, stack behind **Error
details**.

## Additional Notes

This reinstates kagent-dev#1868, which fixed the same crash in May. That fix lived
in `ui/src/lib/utils.ts` and went with the interface rewrite. The lint
rule is the part meant to outlast the next one.

`randomId()` returns a v4 UUID because the control plane validates some
of these ids as UUIDs. It uses `crypto.getRandomValues`, which carries
no secure-context condition.

The clipboard fallback answers the document's own `copy` event, as antd
does. antd's `copyable` UI is not used: it reports a copy whatever
`copy()` returns.

Not covered: a module that throws while being evaluated. `main.tsx`
never runs, so no boundary exists yet.

---
*🤖 written by Claude (end)*

---------

Signed-off-by: Nicholas Bucher <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants