Redact secrets an MCP server returns, not only the credentials we hand out #144

Open
opened 2026-10-13 19:07:01 +00:00 by dev-agent · 0 comments
Collaborator

Context. Under L12, every value the harness hands out is scrubbed from tool output before it reaches the transcript, a model or a log. nisse_core.execution.redact matches exact values. For MCP tools (M7.2, X3), we decided to start with the same approach: scrub each instance's own configured credential from its responses.

The gap. An API can return secrets the harness never knew:

  • UniFi: Wi-Fi passphrases (x_passphrase), RADIUS secrets, VPN pre-shared keys;
  • Proxmox: cloud-init passwords (cipassword), API token details, storage credentials.

Exact-value scrubbing can't catch these. It also misses a known secret when it comes back encoded (base64, URL-encoded) or split across lines.

To look at:

  • Masking by field, per server: keys or JSON paths to mask or drop. These would live in versioned policy, like O2's, where a model may only propose entries through a PR.
  • Possibly a default deny-list of common key names (password, secret, token, psk, passphrase, ...), which can only ever make masking stricter.
  • The encoded forms of the values we hand out (base64, URL-encoded).
  • Tests built from recorded responses of the servers we actually run.

Decided with the operator (2026-10-13): scrubbing the known credentials is enough for M7.2. This issue is the later improvement.

🤖 Generated with Claude Code

**Context.** Under L12, every value the harness hands out is scrubbed from tool output before it reaches the transcript, a model or a log. `nisse_core.execution.redact` matches exact values. For MCP tools (M7.2, X3), we decided to start with the same approach: scrub each instance's own configured credential from its responses. **The gap.** An API can return secrets the harness never knew: - UniFi: Wi-Fi passphrases (`x_passphrase`), RADIUS secrets, VPN pre-shared keys; - Proxmox: cloud-init passwords (`cipassword`), API token details, storage credentials. Exact-value scrubbing can't catch these. It also misses a known secret when it comes back encoded (base64, URL-encoded) or split across lines. **To look at:** - Masking by field, per server: keys or JSON paths to mask or drop. These would live in versioned policy, like O2's, where a model may only propose entries through a PR. - Possibly a default deny-list of common key names (`password`, `secret`, `token`, `psk`, `passphrase`, ...), which can only ever make masking stricter. - The encoded forms of the values we hand out (base64, URL-encoded). - Tests built from recorded responses of the servers we actually run. **Decided with the operator (2026-10-13):** scrubbing the known credentials is enough for M7.2. This issue is the later improvement. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dev/nisse#144