What it detects
Offline PII / sensitive-personal-data scanner for AI agent transcripts and logs.
Before you share a run, drop it into a ticket, or ship it to a log pipeline, piiguard checks whether emails, phone numbers, SSNs, payment cards, government IDs, bank details, dates of birth, home addresses, or medical record numbers leaked into messages or tool results. It can also write a redacted copy (--redact).
Standard library only. It never connects to a network.
Rules
| Rule | Severity | What it flags |
|---|---|---|
| PG01 | high | Email address |
| PG02 | high | Phone number (NANP / simple international) |
| PG03 | critical | US Social Security number (labeled or dashed; invalid area/group rejected) |
| PG04 | critical | Payment card PAN (Luhn + loose issuer prefix) |
| PG05 | high | Passport / driver's-license / national-ID (labeled), including UK NINO, Canadian SIN, ICAO TD3 MRZ, Indian Aadhaar, Brazilian CPF, Australian TFN, Swedish personnummer, Polish PESEL, Singapore NRIC, French NIR, Japan My Number, and Mexican CURP (checksums required where the identifier validates) |
| PG06 | high | IBAN (MOD-97), ABA routing, bank account number (labeled / JSON keys) |
| PG07 | medium | Date of birth (labeled) |
| PG08 | medium | Street / postal address heuristic |
| PG09 | medium | Medical record number / NPI (labeled) |
| PG10 | info | Inventory of segments scanned (disable in CI with --disable PG10) |
Usage
python3 piiguard.py transcript.json [more.jsonl dir/ -]
--as-text treat inputs as plain text (paragraph = segment)
--disable RULE ... skip rule ids (e.g. PG10 PG01)
--json machine-readable output
--min-severity S hide findings below S (default info)
--fail-on S exit 1 if any finding >= S (default high; any, none)
--redact OUT write redacted copy (file for one input, directory for many)
--list-rulesAfter pip install of the kit, the same options work as agentsec piiguard …. Every tool also accepts --help and almost every tool accepts --json.
Example output
Flags SSN (PG03), card (PG04), email/phone (PG01/PG02), passport (PG05), bank fields (PG06), DOB/address/MRN (PG07–PG09); exit 1. (Those JSON fixtures are gitignored because they embed Luhn-valid demo PANs; always regenerate with make_examples.py.)
Email-only JSONL works without generation. --redact writes a copy with matches replaced by [REDACTED:PG0x:…] tokens.
examples/clean_openai.json is clean under --fail-on high (exit 0).
python3 examples/make_examples.py # writes synthetic SSN/card fixtures locally
python3 piiguard.py examples/risky_openai.json --disable PG10
SARIF and CI
agentsec piiguard path/to/input --sarif > piiguard.sarif
# GitHub Actions (composite action ships with the repo)
- uses: dunkleschitz/agentsec@v0
with:
tools: piiguard
paths: path/to/input
fail-on: high
SARIF 2.1.0 can be uploaded to GitHub code scanning. The composite action writes per-tool reports under agentsec-sarif/ by default.
OWASP mapping
Heuristic mapping of what this tool helps a reviewer look for. Not an official OWASP endorsement, and not complete coverage of any item. Sources: OWASP Top 10 for LLM Applications 2025 and OWASP Top 10 for Agentic Applications 2026.
- LLM02 Sensitive Information Disclosure — OWASP LLM Top 10 (2025)
Known limits
- Heuristic regex + checksums. Novel formats, non-US national IDs without labels,
and non-Latin addresses are often missed; order IDs and random digit runs can false-positive — review snippets.
- Card detection needs a Luhn-valid PAN with a plausible issuer prefix; truncated
or encrypted card tokens are invisible.
- Bare 9-digit SSNs without dashes or a nearby label are ignored on purpose.
- Only sees what was logged. Redaction rewrites text spans; it does not prove a
downstream system forgot the original.
- A clean piiguard result does not mean the transcript is free of secrets — run
tracesweep for credentials.
Full source, tests, and fixtures: tools/piiguard/ in the repository. Install the kit with pip install git+https://github.com/dunkleschitz/agentsec.git.