ADRs
0021, xterm.js secrets sanitizer in Daedalus
How Daedalus prevents accidentally surfacing secrets to operators
Status: Accepted Date: 2026-04 Stakeholders: Bobby Nannier
Context
Daedalus's embedded terminal (xterm.js) runs shell commands like gh, doctl, ssh. Many of these output secrets:
gh auth statusshows the user's GitHub PAT.doctl auth initechoes the DigitalOcean API token.podman exec ... cat .env.prodshows every production secret.psql ... '\d'shows table contents including encrypted-but-not-yet-decrypted data.
Naive display would put secrets in:
- The on-screen terminal (operator's eyes, screen recordings, screenshots).
- Daedalus's log file (which the operator might attach to a bug report).
- Screenshots taken by the MCP
screenshottool (which Claude or another agent receives).
Decision
All terminal output flows through a sanitizer regex that redacts known-secret patterns before display, logging, and screenshot capture.
Implemented in daedalus/src-tauri/src/commands/pty.rs and matched against src/lib/sanitize.ts on the frontend.
Patterns matched:
Bearer <token>→Bearer [REDACTED]Authorization: <anything>→Authorization: [REDACTED]RE_xxxxxxxxxxxx(Resend API key prefix) →RE_[REDACTED]dop_v1_*(DigitalOcean PAT prefix) →dop_v1_[REDACTED]ghp_*,gho_*,ghr_*,ghu_*(GitHub tokens) →ghp_[REDACTED]postgres://user:<pass>@...→postgres://user:[REDACTED]@...eyJ.*\.eyJ.*\.(JWT-ish strings) →[REDACTED-JWT]
Consequences
- Operator-visible terminal is safe to screenshot. Useful for bug reports.
- MCP screenshot tool is safer. Claude's view of the wizard doesn't include raw secrets even if a command happened to print one.
- False positives possible. If a non-secret string matches a redaction pattern, it's silently redacted. Acceptable trade-off.
- False negatives possible. A secret format we haven't pattern-matched gets through. The list grows as we encounter new formats; not breaking.
Limitations
- The sanitizer does not apply to in-app form fields that the operator types (the Secrets wizard page shows secrets as the operator enters them, by design).
- A
terminal_execcommand that runscat secrets-fileand the file format isn't on the pattern list will leak.