Olympus Docs
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 status shows the user's GitHub PAT.
  • doctl auth init echoes the DigitalOcean API token.
  • podman exec ... cat .env.prod shows 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 screenshot tool (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_exec command that runs cat secrets-file and the file format isn't on the pattern list will leak.

On this page