Redact secrets before your AI agent sees them
Project description
pyveil
Redact secrets before your AI agent sees them.
pyveil is agent-native redaction middleware for prompts, tool calls, MCP resources, logs, traces, and memory. Put it before sensitive context reaches a model, tool, memory store, trace exporter, or log sink.
user data / tool data / resource data
-> pyveil
-> agent prompt / tool call / MCP resource / memory / trace / log
pyveil is intentionally small: standard-library core, deterministic HMAC placeholders, channel-aware policy, and high-precision detectors for v0.1.
Install
pip install pyveil
Python 3.8 through 3.14 are tested.
30 Second Quickstart
from pyveil import Veil
veil = Veil.high(secret=b"tenant-or-run-secret", scope="tenant/session")
result = veil.redact_text(
"Email alice@example.com and call 010-1234-5678",
channel="prompt.input",
)
print(result.text)
# Email [EMAIL:...] and call [PHONE:...]
For one-off scripts:
from pyveil import redact_text
safe = redact_text(
"email alice@example.com",
secret=b"tenant-or-run-secret",
scope="tenant/session",
)
print(safe.text)
Usage Guides
Short no-audio walkthroughs are attached to the v0.1.1 GitHub release:
Why Middleware
Prompt-only redaction asks the model to handle sensitive data after the model has already seen it. pyveil redacts before context crosses an agent boundary.
Classic PII masking libraries usually treat redaction as "text in, text out." Agents leak through more surfaces:
| Channel | Typical use |
|---|---|
prompt.input |
User or retrieved context before model input |
prompt.output |
Model output before display or chaining |
tool.call.arguments |
Arguments before a model-controlled tool runs |
tool.call.result |
Tool results before returning to the model |
mcp.resource.content |
MCP resource content before agent use |
memory.write |
Memory text before embedding or persistence |
trace.span.attributes |
Observability attributes before export |
log.record |
Application logs before handlers or sinks |
Channels are first-class so policy can decide whether a finding should be redacted, passed, or blocked.
Text Redaction
from pyveil import Channel, Veil
veil = Veil.high(
secret=b"tenant-secret",
scope="tenant_123/session_456",
max_input_chars=1_000_000,
)
safe = veil.redact_text(
"Authorization: Bearer synthetic-token-value",
channel=Channel.PROMPT_INPUT,
)
print(safe.text)
print(safe.findings[0].type)
Finding objects do not contain raw sensitive values by default. They include metadata such as type, detector, rule_id, path, placeholder, and fingerprint.
Structured Redaction
Use redact_data for dictionaries, lists, JSON strings, tool arguments, MCP-like payloads, trace attributes, and memory records.
from pyveil import Veil
payload = {
"user": "alice@example.com",
"headers": {"Authorization": "Bearer synthetic-token-value"},
"args": {"phone": "+82 10-1234-5678"},
"debug": True,
}
veil = Veil.high(secret=b"tenant-secret", scope="tenant/session")
safe = veil.redact_data(payload, channel="tool.call.result")
print(safe.data)
Structured payloads keep their shape. Non-string scalar values under sensitive key names, such as {"api_key": 12345} or {"password": True}, preserve their original type instead of being replaced with strings.
HIGH vs LOW
Use HIGH by default for agents and external boundaries.
| Level | Intended use | Example |
|---|---|---|
HIGH |
Agent, model, tool, MCP, memory, trace, and log boundaries | alice@example.com -> [EMAIL:a13f7c91b0d2] |
LOW |
Human-facing diagnostics or legacy-style previews | alice@example.com -> al***@e******.com |
Credential-like values remain aggressively hidden. There is no reversible vault or unmasking API in v0.1.
Policy
The default policy redacts supported findings and blocks credential-like material in tool.call.arguments.
from pyveil import Action, Channel, Entity, Policy, Veil
policy = Policy.default_high().override(
Channel.PROMPT_INPUT,
Entity.EMAIL,
Action.PASS,
)
veil = Veil.high(secret=b"tenant-secret", policy=policy)
When both policy and level are supplied, the explicit policy decides channel levels and actions. Build one Veil per tenant, session, or run and reuse it in tight loops.
CLI
pyveil init
export PYVEIL_SECRET="tenant-or-run-secret"
export PYVEIL_SCOPE="tenant/session"
pyveil redact prompt.txt --channel prompt.input --level high
pyveil redact request.json --channel tool.call.result --format json
pyveil scan prompt.txt --format json
pyveil test-config pyveil.yaml
JSON-shaped input is treated as structured data. Use --format json for pyveil redact when the input is JSON.
Detectors
v0.1 focuses on high-precision, low-dependency detection:
- Email addresses
- Korean and international-ish phone numbers
- Credit card numbers with Luhn validation
- JWTs
- Bearer and Basic authorization headers
- Private key blocks
- Common API key and provider token prefixes
- URL query secrets such as
access_token= - Key-value secrets in text and structured payloads
Broad name and address detection is intentionally out of scope for core v0.1 unless supplied as known values or custom rules in a future release.
Safety Model
pyveil aims to reduce sensitive-context exposure at agent boundaries.
- No raw sensitive value is stored in
Findingby default. - Stable placeholders use HMAC-SHA256 with caller-provided secrets.
scopeseparates placeholders across tenants, sessions, or runs.max_input_charslimits input size before detection.- Core v0.1 has no network calls and no required third-party runtime dependencies.
Use it with access control, logging discipline, secret scanning, provider-side controls, and normal application security review.
Non-goals
pyveil is not:
- A Presidio clone
- An enterprise DLP system
- A compliance guarantee
- A secret-scanning replacement
- A prompt-injection firewall
- A reversible token vault
Agent Adoption
This repository includes files meant for coding agents and LLM readers:
- AGENTS.md for agent instructions
- llms.txt for LLM-friendly navigation
- docs/threat-model.md
- docs/known-limitations.md
- docs/detector-provenance.md
- docs/release-checklist.md
- docs/integrations/mcp.md
- docs/integrations/logging.md
- docs/integrations/tracing.md
Examples:
- examples/basic_usage.py
- examples/redact_json.py
- examples/log_filter.py
- examples/mcp_tool_result.py
- examples/memory_write.py
Development
uv run --extra dev ruff check .
uv run --extra dev mypy pyveil tests
uv run --extra test pytest
Full local release check:
for v in 3.8 3.9 3.10 3.11 3.12 3.13 3.14; do
UV_PROJECT_ENVIRONMENT="/tmp/pyveil-venv-$v" uv run --python "$v" --extra test pytest -q --disable-warnings --no-cov
done
uv run --extra dev python -m build
uv run --extra dev python -m twine check dist/*
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyveil-0.1.1.tar.gz.
File metadata
- Download URL: pyveil-0.1.1.tar.gz
- Upload date:
- Size: 299.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
09b3c190b21136c4accf58f98396a7e330c5f4904a8ef33cecb7a5515b9a8ec3
|
|
| MD5 |
026bcaaac7d08a3c9133f2a30a5d2c0b
|
|
| BLAKE2b-256 |
a5328dde22fc46307b4f538abd9b7193782c9ae05e7e421e5c7d01f3478fd869
|
Provenance
The following attestation bundles were made for pyveil-0.1.1.tar.gz:
Publisher:
release.yml on hyeonsangjeon/pyveil
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyveil-0.1.1.tar.gz -
Subject digest:
09b3c190b21136c4accf58f98396a7e330c5f4904a8ef33cecb7a5515b9a8ec3 - Sigstore transparency entry: 1981236385
- Sigstore integration time:
-
Permalink:
hyeonsangjeon/pyveil@49018772ea842c6814054f1b4eb642b0515026fd -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/hyeonsangjeon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@49018772ea842c6814054f1b4eb642b0515026fd -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyveil-0.1.1-py3-none-any.whl.
File metadata
- Download URL: pyveil-0.1.1-py3-none-any.whl
- Upload date:
- Size: 22.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
91a83ed393c2e5f6669b421809cacfb7fa569c2247fcabfc641fd4861a6ec004
|
|
| MD5 |
0a1a71bc61bab43e9abcaec7ec92c948
|
|
| BLAKE2b-256 |
c62f54feff88e91513714bf2e4a55c344d2d6e06fcd2cf9a8c932588e7eda07a
|
Provenance
The following attestation bundles were made for pyveil-0.1.1-py3-none-any.whl:
Publisher:
release.yml on hyeonsangjeon/pyveil
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyveil-0.1.1-py3-none-any.whl -
Subject digest:
91a83ed393c2e5f6669b421809cacfb7fa569c2247fcabfc641fd4861a6ec004 - Sigstore transparency entry: 1981236451
- Sigstore integration time:
-
Permalink:
hyeonsangjeon/pyveil@49018772ea842c6814054f1b4eb642b0515026fd -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/hyeonsangjeon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@49018772ea842c6814054f1b4eb642b0515026fd -
Trigger Event:
release
-
Statement type: