Skip to content

feat: PII/secret masking in LLM traffic #94

Description

@thejoeejoee

Complement to #93 (credential proxy). Even with API keys hidden from the agent, the agent can still leak sensitive data from the codebase (credentials found in source, PII from databases, internal URLs, etc.) to LLM providers via request bodies.

Problem

# Agent reads a config file containing a database password:
DB_PASSWORD=s3cret123

# Agent sends it to the LLM as part of the conversation:
POST https://api.anthropic.com/v1/messages
{"messages": [{"content": "I found this config: DB_PASSWORD=s3cret123 ..."}]}

The LLM provider now has the database password. Even if the agent didn't intend to leak it, the secret is in the training/logging pipeline.

Goal

Scan LLM request/response bodies for secrets and PII — replace with reversible placeholders before sending to the provider, restore originals in responses. The agent works normally but sensitive data never leaves the container.

Prior art

Detailed research in #93 comment. Top candidates:

Tool Language Latency Reversible Notes
CloakPipe Rust 3.2ms AES-256-GCM vault, 5-layer detection, F1 0.94, streaming, MCP server
PasteGuard TS/Bun 97ms Microsoft Presidio, 30+ PII types, 24 languages, dashboard
mirage-proxy Rust <1ms ✅ (fakes) Plausible fake values instead of tokens, 129 patterns
LLM Guard Python varies Most mature (2.7K★), 20+ scanners, not reversible
LiteLLM + Presidio Python varies Multi-provider routing, most flexible
AegisGate Python varies PII + prompt injection + response sanitization

Integration with OpenCode

OpenCode supports baseURL override per provider and HTTP_PROXY/HTTPS_PROXY env vars — both work for routing traffic through a masking proxy. See integration research.

Possible approach

PII masking proxy as a sidecar container (same as credential proxy in #93, could be the same proxy process):

  1. Proxy receives LLM request from OpenCode
  2. Scans request body for secrets (API keys, passwords, tokens) and PII (names, emails, IPs)
  3. Replaces with reversible placeholders ([[SECRET_1]], [[EMAIL_1]])
  4. Forwards to provider (after credential injection from feat: credential proxy — agent uses API keys without seeing them #93)
  5. On response, reverses placeholders so the agent sees original values

Relationship to other issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew functionalityneeds-designRequires design discussion before implementationsecuritySecurity hardening or vulnerability

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions