| name | pii-scan |
| description | Scan files, directories, or git repositories for personally identifiable information — credentials (gitleaks) plus broader PII like emails, phone numbers, addresses, names, ID numbers, IPs, IBANs (Microsoft Presidio). Cross-references a user-maintained personal PII inventory to flag matches against the user's own real data as high severity. Triggers on phrases like "scan for PII", "check for personal data", "is my address in this folder", "leaked personal info", "presidio scan". |
PII Scan
Scans a target — a single file, a directory tree, or one or many git repositories (working tree + history) — for:
- Credentials & secrets — via
gitleaks (or trufflehog as fallback).
- Generic PII — via Microsoft Presidio's analyzer (emails, phones, addresses, names, IDs, IPs, IBANs, credit cards, etc.).
- Personal-inventory matches — the user's own real PII (home address, family names, personal phone, ID numbers) loaded from a private inventory file. These are scored HIGH severity when they appear in a public git repo.
Output is a per-target report with file:line hits, severity, and redaction suggestions. Read-only — never modifies any file.
First-run setup
Personal PII inventory
Resolve plugin data dir: ${CLAUDE_USER_DATA:-${XDG_DATA_HOME:-$HOME/.local/share}/claude-plugins}/pii-scanner/.
Inventory path: <plugin-data-dir>/pii-inventory/personal.yaml.
If the file doesn't exist, scaffold it with empty fields and walk the user through filling it. Suggested categories:
identity:
full_names: []
birthdate: ""
national_ids: []
addresses:
home: []
previous: []
contact:
personal_emails: []
personal_phones: []
emergency_contacts: []
financial:
iban: []
bank_accounts: []
credit_card_last4: []
family:
names: []
birthdates: []
medical:
conditions: []
providers: []
notes: |
Free-form notes about anything else to treat as personal.
The inventory file is never sent anywhere; it stays local. State this clearly during setup.
Tooling
Confirm/install:
gitleaks — which gitleaks or apt install gitleaks / install from GitHub releases.
presidio-analyzer — Python package: pip install presidio-analyzer presidio-anonymizer && python -m spacy download en_core_web_lg.
If not installed, offer to install. Both are optional but at least one must be present. If neither is available, fall back to a basic regex sweep (emails, phones, IBANs, common credential patterns) and tell the user the scan is degraded.
Procedure
1. Choose target
The user can scan:
- A single file — read the file, run Presidio + regex; gitleaks is skipped.
- A directory tree (non-repo) — walk the tree, scan each text file. Skip binary files and files > 5 MB.
- A single git repository — current directory or a named path.
- A folder of repos — every immediate subdirectory containing
.git/.
- A subset of GitHub clones — intersect a list of remote repos with locally cloned copies.
For git repos, ask: scan only working tree (fast) or also git history (slow, comprehensive)?
2. Run gitleaks (credentials layer)
Only applicable for git repos. Per repo:
gitleaks detect --source <repo> --report-format json --report-path <tmp>/gitleaks-<repo>.json --no-banner [--no-git for working-tree-only]
Capture findings: rule, file, line, commit hash (if history mode), match excerpt (redacted in display).
For non-repo targets, skip gitleaks and rely on Presidio + regex for credential-like patterns.
3. Run Presidio (PII layer)
For each tracked file (working-tree mode), each blob in history (history mode), or each file in a directory walk, feed text content to Presidio's analyzer with these recognizers enabled by default:
EMAIL_ADDRESS, PHONE_NUMBER, IP_ADDRESS, CREDIT_CARD, IBAN_CODE, US_SSN, LOCATION, PERSON, DATE_TIME, URL, US_PASSPORT.
- Add country-specific recognizers as appropriate (e.g. an Israeli teudat zehut 9-digit-with-checksum recognizer); document any custom ones in the report.
Skip binary files (file --mime check) and very large files (> 5 MB), with a note.
Stream content — don't load every file into memory at once.
Custom recognizers from inventory
Build custom Presidio recognizers from the user's inventory:
- For each entry in
identity.full_names, build a PatternRecognizer for the literal string (case-insensitive).
- For each
addresses.home entry, build a recognizer for the full string AND for each line of the address (street, city, postcode).
- For each phone, normalise to digits only and match both the digit form and common formatted forms (e.g.
050-123-4567, +972 50 123 4567, (555) 123-4567).
- For each ID, exact-match.
- For each family name, recognizer with medium base score (names are common; reduces false positives).
These custom recognizers carry a tag inventory_match so they're easy to elevate in scoring.
4. Severity scoring
For each finding:
- Critical — credential leak (gitleaks).
- High — inventory_match in a public repo (use
gh repo view to check visibility, when applicable).
- High — credit card / IBAN / ID number with high Presidio confidence.
- Medium — generic PII (email, phone, address) NOT in the inventory.
- Medium — inventory_match in a private repo or non-repo target (still worth knowing about).
- Low — common names, generic locations, dates with low Presidio confidence.
5. Report
Per target:
## <target> (<visibility or "directory" or "file">)
### Critical (N)
| File | Line | Type | Excerpt (redacted) | Source |
|------|------|------|--------------------|--------|
### High (N)
...
### Medium (N)
...
Also generate a top-level summary across all scanned targets.
Save the full report (with raw matches, NOT in conversation) to <plugin-data-dir>/pii-scan-reports/YYYY-MM-DD-HHMM/.
In the conversation, show only counts and redacted excerpts (e.g. ***@example.com, +***-***-4567) — never echo back actual PII. This prevents the scan output itself from becoming a leak.
6. Resolution suggestions
For Critical and High findings, suggest:
- Public repo with inventory match — recommend making private (
gh repo edit --visibility private) OR scrubbing the file and force-pushing (with the usual warnings about rewriting history).
- Credential leak — note the finding and the file:line. Recommend rotation if the user wants to know; otherwise just surface it.
- History matches — point at
git filter-repo for scrubbing; warn that anything pushed publicly should be considered exposed regardless.
- Directory / file targets — suggest manual redaction or
.gitignore patterns if the path is inside a repo working tree.
Do not perform any rewriting automatically — these are user-only decisions.
Notes
- The inventory file is the single most sensitive file this plugin manages. Never commit it, never echo it, never include it in any report file outside
<plugin-data-dir>/.
- Add
pii-inventory/ to a .gitignore if <plugin-data-dir> ever overlaps with a repo (it shouldn't, but defence in depth).
- The skill is read-only. Always.