Stop Sending PII to OpenAI & Claude: A Rust Proxy That Redacts First
Your engineers are sending customer data to OpenAI right now. Not on purpose. Not maliciously. But every curl to a chat completion endpoint, every error report to Sentry, every analytics event — carries the risk of PII leaving your perimeter.
The standard fix is policy: “don’t put PII in prompts.” That works until a support tool auto-includes the customer’s email in context. Or until a debugging session pipes a raw request body to GPT-4 to explain the error. The discipline model breaks the moment your team scales past the people who wrote the policy.
Bleep Gateway enforces it at the wire level instead.
The Problem: Every LLM Call Is a Data Exfiltration Vector
When you call an LLM API, your request body travels to infrastructure you don’t control. If a user typed their email, phone number, or national ID into a prompt, that data is now in a third-party system. Some providers use request data for model training unless you explicitly opt out — and “opted out” is a legal assertion, not a technical guarantee.
This isn’t hypothetical. Three real patterns I’ve seen:
- Support copilot pulls customer records into context. Every question about “user 12345” sends their full profile to the LLM endpoint.
- Code assistant receives a
.envfile pasted into the editor. AWS keys, database passwords, API tokens — all sent as prompt context. - Error monitoring (Sentry, Datadog) captures the full request payload when an exception fires. For a healthcare API, that’s patient data in a third-party log.
How Bleep Solves It
Bleep is a transparent MITM proxy. Route outbound HTTP/S through it, and it inspects every request body before forwarding. When it finds sensitive data, it replaces it with a format-preserving fake. The original never leaves your network.
your service / LLM agent │ ▼bleep proxy ← detects PII, replaces with fakes │ ▼OpenAI / Claude / third-party API (sees only fake values)The key insight: replaced values keep their format. Emails stay valid-looking. Credit card numbers remain Luhn-valid. AWS keys preserve their AKIA prefix. JWTs stay structurally valid. Downstream services don’t break because the data shape hasn’t changed — only the sensitive content.
Why Not Just [REDACTED]?
Because everything breaks. JSON schema validation fails. String length constraints reject the request. Type-checking middleware throws. And you can’t correlate redacted logs back to specific users for support cases.
Format-preserving encryption (AES-FF1) produces a different value in the same format. It’s deterministic with a key — the original is recoverable when you need it. [REDACTED] is a one-way street.
# example rule: French national ID (INSEE)- id: ha.pii.fr-insee name: French INSEE Number regex: '\b[12][0-9]{2}(0[1-9]|[1-9][0-9])(2[AB]|[0-9]{2})[0-9]{3}[0-9]{3}[0-9]{2}\b' keywords: ["insee", "secu"] replacement_type: fpe_numeric # AES-FF1, same format, recoverable severity: mediumOther replacement strategies ship built-in: faker_cc_luhn (random Luhn-valid card), faker_aws_key (preserves AKIA prefix), faker_github_pat (preserves ghp_ prefix), faker_jwt (structurally valid JWT), faker_db_conn (replaces credentials, keeps host/port).
Detection: Fast on Clean Traffic
The detection pipeline is designed for the 99% case: most requests contain no PII. Running 200+ regexes against every health check would kill throughput.
Stage 1: Aho-Corasick pre-filter. At startup, Bleep builds an automaton from keyword lists across all rules. Bodies without any keyword are rejected in a single pass — no regex runs. For clean traffic, this is the entire cost.
Stage 2: Per-rule regex with validators:
- Shannon entropy — rejects low-entropy matches like
AAAAAAAAAAAAAAAA - Luhn checksum — validates credit card digit sequences
- Context proximity — boosts confidence when a keyword like
"token":appears near a match
Rules merge from gitleaks, detect-secrets, nosey-parker, and a hand-authored set covering EU PII patterns (French INSEE, German Steuer-ID, Polish PESEL, UK NI numbers).
Running It With Your LLM Stack
cargo run --bin bleep-gateway -- --port 9190 --min-confidence lowPoint your LLM client at it:
export HTTPS_PROXY=http://127.0.0.1:9190Now every call to OpenAI, Anthropic, or any external API goes through Bleep first. Redactions are logged to a JSONL audit file — the original value stays on local disk, the fake goes over the wire.
The bleep-tui binary shows redactions in real time:
cargo run --bin bleep-tui# live stream of: rule_id, category, original → fake, destinationWhat It Doesn’t Cover (Yet)
- Streaming responses — Bleep buffers full bodies before forwarding. Streaming adds latency from buffering. Chunk-boundary pattern matching is a known hard problem.
- Binary content — images, PDFs, protobuf pass through uninspected. OCR-based detection is tracked as a future extension.
- Unstructured PII — names, addresses in free text don’t match regex patterns. This needs an ML detection path.
Why This Matters for AI Teams
Every company building with LLMs has this problem. The more you integrate AI into workflows — support, coding, analytics, search — the more data flows to external endpoints. Bleep is the enforcement layer that lets you ship AI features without becoming a compliance story.
It’s not about trusting or not trusting your LLM provider. It’s about having a technical control that works regardless of policy, training, or terms of service updates.