Skip to main content

PrivAiTe

Your coding agent reads your .env files, logs and command output, and everything it reads goes to the LLM provider. PrivAiTe is a local proxy that replaces the secrets and personal data in every request before it leaves your machine, then puts the personal data back in the reply.

CI Python 3.11+ License PyPI

# your agent reads and sends:
OPENAI_API_KEY=sk-demo-fake000
DB_PASSWORD=demo-pass-4821
ADMIN_EMAIL=marie@example.com
# the provider receives:
OPENAI_API_KEY=[SECRET]
DB_PASSWORD=[SECRET]
ADMIN_EMAIL=<EMAIL_ADDRESS_1>

That is real engine output with the shipped config, not a mock-up. In the reply, <EMAIL_ADDRESS_1> becomes the real address again, streaming included. [SECRET] does not come back: the shipped configs redact secrets and mask card numbers for good, a per-type setting. Detection runs locally and is best-effort, not a guarantee: the threat model says what it does not cover.

See it work in one command, no API key

docker run --rm \
  ghcr.io/crp4222/privaite:0.8.0 \
  python -m privaite verify
  value                                          where                  direct   proxied
  Marie Dupont                                   message text             LEAK     clean
  marie.dupont@example.invalid                   tool-call argument       LEAK     clean
  4111 1111 1111 1111                            tool-call argument       LEAK     clean
  SERVICE_API_KEY=sk-demo-0000-not-a-real-key    tool output              LEAK     clean
RESULT: PASSED, every planted value was replaced before the request left.

It starts a throwaway provider on 127.0.0.1, sends the same agent-shaped request straight to it and then through PrivAiTe, and prints what each request body contained: every planted value shows LEAK when sent directly and clean through the proxy. About 20 seconds on a laptop CPU once the image is pulled (it carries the detection model and takes about 3 GB on disk). With pip, privaite verify does the same after the install below; its first run downloads the model (about 900 MB). It exits non-zero if a value leaks: docs/verify.md.

Quick start

Docker: the detection model is baked in, so it runs offline. PRIVAITE_API_KEYS is the key your client sends to PrivAiTe (pick any value); OPENAI_API_KEY is your real provider key, which stays in the container.

docker run -d -p 8400:8400 \
  -e PRIVAITE_API_KEYS=change-me \
  -e OPENAI_API_KEY=sk-... \
  ghcr.io/crp4222/privaite:0.8.0

pip: the same proxy with the same shipped config, which exposes gpt-4o-mini and gpt-4o.

python -m pip install --upgrade "privaite>=0.8.0"
python -m spacy download en_core_web_lg && python -m spacy download fr_core_news_md
curl -fsSLO https://raw.githubusercontent.com/crp4222/PrivAiTe/v0.8.0/config/privaite.openai.yaml
OPENAI_API_KEY=sk-... PRIVAITE_API_KEYS=change-me python -m privaite --config privaite.openai.yaml

Connect: point any OpenAI-compatible client at http://localhost:8400/v1 with the key change-me (from Open WebUI running in Docker: http://host.docker.internal:8400/v1). For Ollama, Azure or any other provider, write your own config and mount it in Docker. The image is also on Docker Hub as crp4222/privaite:0.8.0, and client snippets are in examples/.

Claude Code and Codex

Gateway mode (opt-in, off by default) speaks the native protocols of agent CLIs. It scrubs each request, tool results and tool-call arguments included, relays the CLI's own auth upstream untouched, and restores the reply.

gateway:
  enabled: true
  anthropic:
    base_url: "https://api.anthropic.com/v1"

Then run ANTHROPIC_BASE_URL=http://localhost:8400 claude. Also set pii.detection_cache.enabled: true: agent CLIs resend the whole conversation every turn, and the cache avoids re-scanning it (the threat model spells out its memory tradeoff). Codex support is beta; setup, scanned surface and limits are in docs/gateway.md. In wire-level captures of real sessions on a repository with 24 planted values, Claude Code sent 24 of 24 to its provider and Codex 20 of 24 when run directly. Through the gateway, none reached it on the small fixture and 2 of 24 did on a larger session: the measurement.

  • Measured, not promised. Those numbers do not establish zero leaks on arbitrary agent traffic.
  • It protects the egress, not the agent. The CLI keeps the real values in its own context and local transcripts.
  • The agent's own prompt is not scanned. The system and instructions fields pass through as-is, and Claude Code puts your CLAUDE.md there.
  • The gateway routes are open. They accept a request that carries no PRIVAITE_API_KEYS value, and the server binds 0.0.0.0 by default with no rate limit: bind it to localhost or keep the port off untrusted networks.

What it does

  • It reads inside the JSON. Tool-call arguments are parsed and scrubbed value by value; tool results and multimodal text parts are scanned like any message.
  • It restores the reply, streaming included, in content, tool calls and reasoning.
  • It fails closed and stays local. If detection errors, the request is blocked, not forwarded. Detection (Presidio plus OpenAI's open privacy-filter model) runs on your machine, with no telemetry: the outbound connections page lists what the dependencies tried to send and how each is turned off.

Benchmark

Solution Recall (span) Recall (strict) False positives Tool-call protection
onnx (default) 85.2% 81.7% 2 / 14 100%
light (full Presidio) 62.7% 58.1% 3 / 14 100%
LiteLLM Presidio guardrail 70.3% 65.3% 3 / 14 0.0%
LLM Guard (Anonymize) 76.9% 74.9% 5 / 14 0.0%

Measured on 120 real documents from the open AI4Privacy pii-masking-200k dataset (458 PII items in DE, EN, FR, IT), plus 14 clean documents for false positives. Read the 100% precisely, it is structural: of the PII PrivAiTe detects in plain text, all of it is also removed from tool-call JSON, so its tool-call leak equals its detection misses (14.8% on this corpus). The two guardrails measured here do not look inside tool-call arguments; other gateways do, and the comparison lists what each project states and when to pick it instead. LLM Guard's model is fine-tuned on this exact dataset, so its recall here is optimistic. Methodology, per-language tables, out-of-distribution checks and reproduction: privaite-bench.

The opt-in minilm and ultrafast presets (0.8.0) run PrivAiTe's own model, crp4222/privaite-pii-minilm, in place of the Privacy Filter. On privaite-bench's 1,607 documents they mask 90.6% and 90.3% of persons against 72.3% for onnx, at a median 39 ms and 10 ms per document against 121 ms; on the corpora the model never trained on, 82.9% and 82.7% against 72.7%. In a live Claude Code session through the gateway, ultrafast leaked 0 of 24 planted values and scrubbed each request in 3.4 s against 23.8 s. Details, false positives on code included: detection.

Integrations

  • Open WebUI filter (setup, hub listing): the engine in-process, no separate proxy. Open WebUI sends its title, tag and follow-up calls without running filters, so with a cloud model use the standalone proxy instead: it sees those calls too.
  • LiteLLM guardrail (setup): a custom guardrail for teams already on the LiteLLM proxy. It anonymizes requests and restores responses inline, including tool-call arguments, which LiteLLM's built-in Presidio guardrail does not scan.

Threat model

PrivAiTe does local pseudonymization, not anonymization: the real-to-placeholder mapping lives in memory for the duration of a request. It protects against the provider storing, training on or logging your raw values: for everything the detector catches, the provider receives placeholders, in message text, tool-call arguments and multimodal text. It does not protect against:

  • Missed detections. Detection is statistical; a value it does not recognize reaches the provider (see the benchmark).
  • Unrecognized secret formats: unknown field names, encoded or split values, bare values without their field context.
  • Re-identification. The surrounding text can stay identifying ("the CEO of <ORG_1> who resigned in March"), and the provider can correlate requests within a session.
  • A compromised local machine. The mapping and the raw text live in local memory.
  • A model inventing a value instead of copying a placeholder: nothing can be restored then.
  • The agent itself, in gateway mode. The CLI keeps the real values locally, and its own prompt is relayed unscanned.

For GDPR or HIPAA, treat this as pseudonymization plus transfer minimization; you remain the data controller. The full version, including what the optional detection cache keeps in memory: docs/threat-model.md.

Docs

  • Presets: onnx is the default. light is faster and needs no model download, but it misses names the default finds: the demo above fails with --preset light. minilm and ultrafast are opt-in: they run PrivAiTe's own model in place of the Privacy Filter, ultrafast on the Apple Neural Engine for agent CLIs on a Mac. Nothing changes unless you set one. Presets
  • Your own types and hard blocks: regex custom_patterns, a per-type fate, and block_entities for what must never leave. Your policy, your types
  • What is scanned and what is not: the exact request fields. API reference
  • Everything else: detection, configuration, redacting PII before an LLM call, changelog, and the same pages as a site: crp4222.github.io/PrivAiTe. To develop: clone, pip install -e ".[dev]", download the two spaCy models above, then python -m pytest tests/.

License

BSD 3-Clause. See LICENSE.

Metadata

Release files for privaite 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for privaite 0.8.0
File Size Uploaded Provenance Actions
privaite-0.8.0.tar.gz 130.0 kB With provenance Details for privaite-0.8.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for privaite 0.8.0
File Interpreter ABI Platform Actions
privaite-0.8.0-py3-none-any.whl Python 3 none any Details for privaite-0.8.0-py3-none-any.whl

Total release size: 265.6 kB

Release files / privaite-0.8.0.tar.gz

Download URL privaite-0.8.0.tar.gz
Size 130.0 kB
Tags Source
SHA-256 checksum
How to use checksums
4a94426ce033f39cdbd6999331b48601414d801dc491f4b3feaa01440eba4211
BLAKE2b-256 checksum
How to use checksums
8168aa1151defd56863537b8dcef1d242bb9ad86a43ee7657da43abaf36b0b88
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 30, 2026.

Transparency log

Release files / privaite-0.8.0-py3-none-any.whl

Download URL privaite-0.8.0-py3-none-any.whl
Size 135.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
126af2c3cf8f4b68049cad7548c703635e44f7f113ccbd1794e87e4b59355bad
BLAKE2b-256 checksum
How to use checksums
5105b7e3c84d252d3079fb8026249a28c841d730c4fd5023702a41109280bcce
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 30, 2026.

Transparency log

Security for privaite 0.8.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for privaite-0.8.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 30, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page