Two kinds of secret leakage happen in AI coding sessions:
- File reads — the AI tool reads your
.env, SSH keys, or credentials from disk - Prompt leakage — you accidentally paste a token into the chat
aifence blocks both.
$ aifence init
Scanning for sensitive files...
Found: .env, config/secrets.yaml, certs/server.pem, .npmrc
Claude Code (detected):
✓ permissions.deny — 26 Read rules added
✓ sandbox.denyRead — 26 patterns added
⚠ Sandbox not enabled — run /sandbox in Claude Code for OS-level Bash protection
Cursor (detected):
✓ .cursorignore — 26 patterns added
Copilot (not detected):
✓ .copilotignore — 26 patterns added
$ aifence prompt-guard install
Installing prompt-guard hooks (global: ~/.claude/settings.json) ...
✓ Hooks installed: UserPromptSubmit, PreToolUse, PostToolUse
Install
pipx install aifence
Or with pip:
pip install aifence
Usage
# Protect your workspace files from AI file reads
aifence init
# Protect your Claude Code prompts from accidental secret leakage
aifence prompt-guard install
# Audit only — no files modified
aifence scan
Part 1 — File protection (aifence init)
The problem
AI coding tools can read any file your user account can access. Most developers have .env files, SSH keys, and credentials sitting in their project directories.
- Claude Code can read files via its Read tool and via
cat .envin Bash - Cursor indexes files for AI context automatically
- Copilot Agent mode runs shell commands with full file access
- Gemini CLI has no file access restrictions at all
What's generated
| Tool | What's generated | Protection level |
|---|---|---|
| Claude Code | permissions.deny (Read rules) + sandbox.filesystem.denyRead |
Full — OS-level when sandbox enabled |
| Cursor | .cursorignore |
Partial — blocks AI reads, not shell |
| Copilot | .copilotignore |
Partial — completions only, not Agent mode |
| Windsurf | .windsurfignore |
Partial — enforcement depth unverified |
| Gemini CLI | Nothing | None — no mechanism exists |
Claude Code: the full picture
Claude Code is the only tool with OS-level protection via its sandbox. aifence generates two layers:
permissions.deny— blocks the Read tool from accessing sensitive filessandbox.filesystem.denyRead— blocks all processes (includingcat,grep,python) from reading those files at the OS level (Seatbelt on macOS, bubblewrap on Linux)
Enable the sandbox yourself: run
/sandboxin Claude Code. aifence adds the rules; enabling is your decision.
Default protected patterns
.env, .env.*, *.pem, *.key, *.p12, *.pfx, *.jks, *.keystore,
credentials, credentials.*, secrets.json, secrets.yaml, secrets.yml,
.secrets, .npmrc, .pypirc, id_rsa, id_ed25519, id_ecdsa,
service-account*.json, *.tfvars, *.tfvars.json, kubeconfig,
.netrc, token.json, .htpasswd
Part 2 — Prompt guard (aifence prompt-guard)
The problem
Even with file protection in place, a single accidental paste — a .env dump into the chat, a curl command with a live Bearer token, a stack trace containing a Stripe key — sends credentials directly to the AI provider's servers.
How it works
aifence prompt-guard install wires three Claude Code hooks that run before any data leaves your machine:
| Hook | What it does |
|---|---|
UserPromptSubmit |
Scans every prompt. Blocks and asks you to resubmit if a secret is found. |
PreToolUse |
Redacts secrets from tool inputs (Bash commands, file writes, web fetches) before execution. The tool still runs — with [REDACTED:aws-access-key] in place of the real value. |
PostToolUse |
Warns Claude not to repeat secrets that appeared in tool output (e.g. aws configure list). |
What gets detected
| Detector | Examples caught |
|---|---|
aws-access-key |
AKIAIOSFODNN7EXAMPLE |
aws-secret-key |
AWS_SECRET_ACCESS_KEY=wJalrXUtn... |
github-token |
ghp_, gho_, ghs_, github_pat_ |
private-key-pem |
-----BEGIN RSA PRIVATE KEY----- |
jwt-token |
eyJ... three-part tokens |
stripe-key |
sk_live_, pk_live_ |
anthropic-key |
sk-ant-api03-... |
openai-key |
sk-proj-... |
gcp-api-key |
AIzaSy... |
pypi-token |
pypi-AgEI... |
slack-token |
xoxb-... |
azure-storage-key |
DefaultEndpointsProtocol=https;AccountName=...;AccountKey=... |
bearer-token |
Authorization: Bearer <token> |
db-connection-string |
postgresql://user:pass@host/db |
basic-auth-url |
https://user:pass@host |
private-key-assignment |
SECRET_KEY = "...", api_secret = "..." |
Custom rules
No code changes or reinstall required. Add your own patterns — or silence noisy built-ins — in ~/.aifence/prompt_guard.toml:
# Silence a built-in that causes false positives
disable = ["jwt-token"]
# Add a company-specific secret pattern
[[rules]]
id = "vault-token"
description = "HashiCorp Vault service token"
pattern = '''hvs\.[A-Za-z0-9_-]{90,}'''
Manage via CLI:
aifence prompt-guard rules list
aifence prompt-guard rules add --id doppler-token --description "Doppler token" --pattern "dp\.st\.[A-Za-z0-9_-]{40,}"
aifence prompt-guard rules disable --id jwt-token
aifence prompt-guard rules enable --id jwt-token
aifence prompt-guard rules remove --id doppler-token
Fail-closed design
- 4-second internal timeout fires before Claude Code's 5-second kill — ensures the hook exits with code 2 (block) rather than silently timing out
- Any unhandled exception exits 2 — a crash never degrades to fail-open
- Malformed JSON input exits 0 — a broken hook packet itself contains no secret
Honest limits
The following bypass techniques are not caught (by design — they require runtime/AST analysis):
base64.b64encode(secret)— encoding destroys the recognisable pattern- Key split across lines or with spaces inserted
- Runtime string concatenation (
"AKIA" + "IOSFODNN7EXAMPLE") - Hex encoding
These require deliberate obfuscation. The guard is designed to stop accidental leakage, which covers 99% of real incidents.
Safe by design
- Pattern-based only — aifence never reads file contents, only matches filenames and text patterns
- Merge, never overwrite — existing configs are preserved
- Idempotent — running any command twice produces the same result
- No network calls — everything runs locally
License
MIT
Metadata
Release files for aifence 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aifence-0.4.0.tar.gz | 19.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aifence-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 45.8 kB
Release files / aifence-0.4.0.tar.gz
| Download URL | aifence-0.4.0.tar.gz |
|---|---|
| Size | 19.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f347c9a1f0d6ef23525f70ea873a6c0d635d6433fed5ebc89b4eb2ef9a4aa46f
|
|
BLAKE2b-256 checksum How to use checksums |
56c54633aa6d9336543db7a9c765554051278f86cb8094c813531ec122b4dd10
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Apr 29, 2026.
Transparency logRelease files / aifence-0.4.0-py3-none-any.whl
| Download URL | aifence-0.4.0-py3-none-any.whl |
|---|---|
| Size | 26.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f2580ed68110c32bb767d5b6d3c230256f07152e19fdcb2b038a75cdd0485241
|
|
BLAKE2b-256 checksum How to use checksums |
c55ca360de6d53ad5c05d21ba9efe064f34bd7a452fab219dc64d5077d0c863b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Apr 29, 2026.
Transparency log