Skip to content

🔴 MCP tool responses bypass final redaction (perseus_get_context, perseus_read, perseus_query) #166

@tcconnally

Description

@tcconnally

Severity: Critical (secret leak via MCP)

Discovered by

Codex code review (2026-06-03)

Location

src/perseus/mcp.py:197 — perseus_get_context calls render_source, not render_output

Problem

perseus_get_context returns the raw, pre-redaction rendered source. Other tool resolvers (perseus_read, perseus_query, etc.) also return their raw output via _call_resolver without passing the result through redact_text.

An MCP client receives unredacted secrets even when redaction.enabled: true is set in config.

Impact

  • Secrets leak via the MCP transport to any tool client
  • Defeats the entire defense-in-depth purpose of the redaction layer for MCP users

Fix

  • Route perseus_get_context through render_output (which applies redaction)
  • In _call_tool / _call_resolver, apply redact_text(result, cfg) to every tool result before returning
  • Document the MCP redaction guarantee in the README

Acceptance criteria

  • Test: configure a redaction rule for SECRET_TOKEN_123, call perseus_get_context, assert response is redacted
  • Test: same for perseus_read, perseus_query, perseus_list, perseus_tree, perseus_date
  • Test: with redaction.enabled: false, the secret IS present (sanity)

Refs

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions