Skip to content

fix(copilot): redact sim_key API keys from persisted Mothership chat messages#4434

Merged
TheodoreSpeaks merged 3 commits intostagingfrom
fix/api-key-mothership
May 4, 2026
Merged

fix(copilot): redact sim_key API keys from persisted Mothership chat messages#4434
TheodoreSpeaks merged 3 commits intostagingfrom
fix/api-key-mothership

Conversation

@TheodoreSpeaks
Copy link
Copy Markdown
Collaborator

@TheodoreSpeaks TheodoreSpeaks commented May 4, 2026

Summary

  • Redact <credential type="sim_key"> tags and generate_api_key tool result keys before persisting assistant messages — DB never stores raw keys, replays show "API key hidden"
  • Coalesce streaming text blocks before redaction so credential tags split across token chunks are caught
  • Capture revealed keys in a page-session ref keyed by both live-stream id and requestId; restore them on read so post-finalize refetch can't clobber the live key the user just generated
  • New shared <ApiKeyReveal> component (with copy button or dots when redacted) used by Mothership chat, settings API-keys modal, and Copilot settings
  • New shared useCopyToClipboard hook, adopted by ApiKeyReveal and CopyCodeButton

Type of Change

  • Bug fix

Testing

Tested manually via Chrome DevTools MCP — generated multiple keys in one chat, refreshed, confirmed redacted "••••••" rendering for prior keys and live-key visibility for the most recent generation. bun run lint and bun run check:api-validation:strict pass. New unit tests (20/20 pass) cover redaction across split chunks, multi-key restore, and request-id fallback.

(localhost key, also removed right after)
image
on refresh:
image

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link
Copy Markdown

vercel Bot commented May 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped May 4, 2026 7:52pm

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 4, 2026

PR Summary

Medium Risk
Medium risk because it changes chat persistence/streaming message shaping (block merging + tool-result rewriting) and client-side restoration logic, which could affect transcript rendering or tool call payloads. Changes are security-sensitive but localized and covered by new unit tests.

Overview
Prevents sim_key values from being stored or re-shown from persisted Mothership chat history by redacting <credential type="sim_key"> tags in assistant content and stripping secrets from generate_api_key tool results before persistence.

Adds a client-side, in-memory cache to capture keys during live streaming and re-inject them after the post-stream refetch, so users can still copy a newly-generated key while older messages remain masked; this also handles credential tags split across streamed text chunks by coalescing assistant text blocks before redaction.

Introduces reusable UI/utilities: a new SecretReveal component for masked-or-copyable secret display, and a shared useCopyToClipboard hook (adopted by CopyCodeButton and key-creation modals).

Reviewed by Cursor Bugbot for commit f54ee3a. Bugbot is set up for automated code reviews on this repo. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 4, 2026

Greptile Summary

This PR prevents raw sim_key API keys from being stored in Postgres by redacting <credential type="sim_key"> tags and generate_api_key tool-result key fields before persisting assistant messages. A client-side page-session cache captures revealed values during the live SSE stream so keys remain copyable in the current session even after the post-stream DB refetch returns the redacted row.

  • P1 — cursor reset across content blocks: restoreRevealedSimKeysForMessage calls restoreInString once per content block, and each call resets cursor = 0. When two API keys span separate (non-consecutive) blocks — e.g., each preceded by its own generate_api_key tool-call block — both blocks are filled with revealed[0]. The user copies the wrong value from the second credential display. message.content (the flat string) is restored correctly; only the per-block path is affected. No existing test covers this case.

Confidence Score: 3/5

Safe to merge for single-key flows; the per-block cursor reset will serve the wrong key value when multiple API keys are generated in one turn and span separate content blocks.

One P1 defect on the changed path: the multi-block restoration cursor resets per block, producing wrong displayed key values for the second+ API key in a multi-key turn. DB redaction (the primary security goal) is unaffected, but the UX correctness of the key-restore feature is broken for the multi-key case. Score is 3/5 (below the P1 ceiling of 4) because the broken path is the core feature this PR introduces.

apps/sim/lib/copilot/chat/sim-key-redaction.ts — restoreRevealedSimKeysForMessage block-mapping loop (lines 244–250); also apps/sim/lib/copilot/chat/sim-key-redaction.test.ts needs a test covering two redacted tags in separate contentBlocks entries.

Important Files Changed

Filename Overview
apps/sim/lib/copilot/chat/sim-key-redaction.ts New write-side redaction and read-side key-restore logic; contains a per-block cursor-reset bug in restoreRevealedSimKeysForMessage that serves wrong key values when multiple keys span non-consecutive content blocks
apps/sim/lib/copilot/chat/persisted-message.ts Wires in mergeAndRedactPersistedBlocks and redactToolCallResult before persisting; logic is correct and well-tested
apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts Adds revealedSimKeysRef, calls captureRevealedSimKeys on every flush, and applies restoreRevealedSimKeysForMessage in the message selector; integration looks correct
apps/sim/components/ui/api-key-reveal.tsx New shared component for displaying or redacting API keys with a copy button; well-structured and reuses useCopyToClipboard
apps/sim/hooks/use-copy-to-clipboard.ts New shared hook; extracts the copy+timer pattern, handles timer cleanup on unmount, and is a clear improvement over 30 inline duplicates
apps/sim/lib/copilot/chat/sim-key-redaction.test.ts Good coverage of single-message and single-block paths; missing a test case for multiple redacted tags across separate contentBlocks entries

Sequence Diagram

sequenceDiagram
    participant SSE as SSE Stream
    participant UC as useChat (flush)
    participant BPA as buildPersistedAssistantMessage
    participant DB as Postgres
    participant SEL as message selector (useMemo)
    participant UI as CredentialDisplay

    SSE->>UC: streaming text chunks (runningText accumulates)
    UC->>UC: captureRevealedSimKeys(revealedSimKeysRef, [assistantId, requestId], runningText)
    Note over UC: in-memory cache: {assistantId → ['sk-sim-...']}

    SSE->>BPA: OrchestratorResult (full content + contentBlocks)
    BPA->>BPA: redactSensitiveContent(content)
    BPA->>BPA: mergeAndRedactPersistedBlocks(contentBlocks)
    BPA->>BPA: redactToolCallResult('generate_api_key', result)
    BPA->>DB: INSERT persisted message (no raw key)

    DB-->>UC: chatHistory refetch (redacted message)
    UC->>SEL: chatHistory.messages.map(toDisplayMessage)
    SEL->>SEL: restoreRevealedSimKeysForMessage(msg, revealedSimKeysRef)
    Note over SEL: looks up cache by msg.id or msg.requestId
    SEL->>UI: ChatMessage with value restored (in-memory only)
    UI->>UI: ApiKeyReveal renders copyable key
Loading

Reviews (1): Last reviewed commit: "fix(copilot): redact sim_key API keys fr..." | Re-trigger Greptile

Comment thread apps/sim/lib/copilot/chat/sim-key-redaction.ts
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a996b75. Configure here.

Comment thread apps/sim/lib/copilot/chat/sim-key-redaction.ts
@TheodoreSpeaks TheodoreSpeaks merged commit ae20d1c into staging May 4, 2026
14 checks passed
@waleedlatif1 waleedlatif1 deleted the fix/api-key-mothership branch May 4, 2026 20:43
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.

1 participant