GeezerVison is showing github.com — fix(copilot): redact sim_key API keys from persisted Mothership chat messages by TheodoreSpeaks · Pull Request #4434 · simstudioai/sim
Conversation
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
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)

on refresh:

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)
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
greptile-apps[bot] and waleedlatif1 reacted with thumbs up emoji
vercel
Bot
commented
May 4, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
| Project |
Deployment |
Actions |
Updated (UTC) |
| docs |
Skipped |
|
May 4, 2026 7:52pm |

|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
cursor
Bot
commented
May 4, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
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.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
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
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this 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.

❌ 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.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
This branch was previously deployed
1 inactive
deployment
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
Milestone
No milestone
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
|