omp packages

@chrisdoc/pi-pii-redact0.4.0

Pi extension to detect and redact PII and sensitive tokens from user prompts, tool results, and context

GitHub Actions Published 7 days ago MIT ~871 downloads/mo

Untested on omp

This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.

Did it work for you?

Result

One report per person. A new report replaces your old one.

Reports 0

No reports yet.

Readme

pi-pii-redact

npm version npm downloads CI License: MIT

A Pi extension that keeps personally identifiable information (PII) and secrets away from the LLM.

Names, addresses, emails, phone numbers, card numbers, government IDs, API keys and more are replaced with stable tokens such as [EMAIL_3#k7q2] before anything is sent to the model. When the model uses those tokens in a tool call or a reply, the extension swaps the real values back in, so your tools still work on real data and you still read real values.

Detection runs locally with the masker-mini multilingual NER model (run through ONNX Runtime) plus deterministic rules using structural, context, and checksum validation as appropriate. Nothing is sent to a third-party service for redaction.

Installation

Requires Pi and Node.js 22 or later.

pi install npm:@chrisdoc/pi-pii-redact

This adds the package to your personal Pi settings (~/.pi/agent/settings.json), so it loads in every session. Start Pi as usual; the footer shows PII: On and redaction is active from the first prompt. Run /pii status to confirm.

On first use the redaction model (about 22 MB) is downloaded from Hugging Face and cached in ~/.cache/pi-pii-redact, so the first session takes a moment longer to start. See The model.

Install size: onnxruntime-node bundles native binaries for all platforms, so the install is larger than the model alone.

Other ways to install

Goal Command
Try it for one session without installing pi -e npm:@chrisdoc/pi-pii-redact
Install for the current project only (.pi/settings.json) pi install -l npm:@chrisdoc/pi-pii-redact
Pin a specific version pi install npm:@chrisdoc/pi-pii-redact@0.2.0
Install from GitHub pi install git:github.com/chrisdoc/pi-pii-redact
Install a local checkout pi install /path/to/pi-pii-redact

Project installs load only after you grant the project trust in Pi.

Update and remove

pi update npm:@chrisdoc/pi-pii-redact   # update this package (pinned versions stay pinned)
pi update --extensions                  # update all installed packages
pi remove npm:@chrisdoc/pi-pii-redact   # uninstall
pi list                                 # show installed packages

Example

You type:

Email jane.doe@example.com that her card 4111 1111 1111 1111 was charged.

The model sees:

Email [EMAIL_1#k7q2] that her card [CREDIT_CARD_1#k7q2] was charged.

If the model then calls a tool with [EMAIL_1#k7q2] as an argument, the tool receives jane.doe@example.com. Its reply is shown and stored with the real values.

Commands

Command Description
/pii or /pii status Show whether redaction is active and how many rules are enabled.
/pii toggle Turn redaction on or off.
/pii enable / /pii disable Turn redaction on or off explicitly.
/pii rules List all rules and whether each is enabled.
/pii stats Show a usage board of redacted and restored items. "This run" counters reset when Pi restarts; protected-value counts come from the session vault.

The enabled state and disabled rules are stored in the session and survive reloads.

What gets redacted

Rules marked "model" use the masker-mini NER model; "rules" are deterministic regex rules whose candidates must pass a checksum or structural check (the model's own email, phone and card labels are not used).

Group Rules Source
People given names, surnames, ages (age) model
Addresses street names, building numbers, cities, ZIP/postal codes model
Contact email addresses, phone numbers, IPv4/IPv6 addresses rules
Financial credit card numbers (Luhn), IBANs (mod-97), ABA routing numbers rules
Government IDs government-id (national IDs, passports, tax IDs, driver's licenses) model
US SSNs, Dutch BSNs (nl-bsn, needs a BSN keyword nearby) rules
Devices IMEI numbers (needs an "IMEI" keyword nearby) rules
Secrets secrets: provider API keys, tokens, JWTs, private keys, credentials in connection URLs (see Secret detection) secret scanner
api-key-generic: sk-…, GitHub ghp_…, GitLab glpat-…, AWS AKIA… (fallback if the scanner is unavailable) rules
Dates date (disabled by default: dates in logs and changelogs are noisy; enable it with /pii toggle date) model

passport, drivers-license and tax-id are aliases of government-id, so toggling them toggles that rule. The state, secondary-address, url and org rules were removed because no detector backs them any more.

Secret detection

The secrets rule ("Secrets & credentials", on by default) uses @visulima/secret-scanner, a Rust port of gitleaks-style detection. It runs the bundled kingfisher rules plus the gitleaks rules that match a distinctive key prefix (about 1,000 rules). The roughly 100 gitleaks "keyword context" rules are left out: they would add about 450 MB of memory and several seconds of start-up for little extra coverage. It finds API keys for Anthropic, OpenAI, Stripe, AWS, Hugging Face, Slack, SendGrid, Google, GitLab and GitHub, JWTs, PEM private keys, credentials in URLs such as postgres://user:pass@host, and password = "..." style assignments. Matches become [SECRET_n#xxxx] tokens that are restored in tool-call arguments and assistant replies like any other token.

  • Offline only: the scanner runs locally and its credential validation (which would send secrets to provider APIs or connect to databases) is hard-coded off.
  • Cost: about 200 MB of memory and a ~1.3 s warm-up, started in the background when a session starts. After that every scanner call has a fixed cost of about 25 ms; a cheap pre-check (long token-like runs, PEM headers, URL credentials, password=/token: style assignments) skips the call for text that cannot contain a secret.
  • Noise control: matches shorter than 8 characters and matches containing whitespace (except private keys) are dropped.
  • Known gaps: npm_ tokens and the AWS documentation example key are not detected by the scanner.
  • Toggle it with /pii toggle secrets (aliases secret, credentials). /pii status shows whether the scanner loaded. If its native binding is unavailable on your platform, secret detection is skipped and the regex-based api-key-generic rule still applies; all PII detection keeps working.
  • Requires Node ^22.14.0 || >=24.10.0.

The model

  • masker-mini (int4, about 22 MB, Apache-2.0) from divergentlabs/masker-mini, derived from Microsoft mDeBERTa-v3 / Multilingual-MiniLM (MIT). See NOTICE.
  • It is downloaded on first use from a pinned Hugging Face revision, verified against pinned SHA-256 hashes and cached in $XDG_CACHE_HOME/pi-pii-redact/masker-mini/<revision>/ (default ~/.cache/pi-pii-redact/...).
  • Offline use: set PI_PII_REDACT_MODEL_DIR to a directory with the same file layout (config.json, tokenizer.json, tokenizer_config.json, onnx/model_int4.onnx). Nothing is downloaded and the hashes are still verified.
  • The default minimumConfidence is 0.55.
  • ONNX Runtime's telemetry is disabled (ORT_DISABLE_TELEMETRY=1 is set before the runtime loads).

Where redaction happens

Pi event What the extension does
input Redacts your prompt before skill or prompt-template expansion.
tool_result Redacts tool output (stdout, file contents, API responses, structuredContent) before it enters the conversation.
context Re-redacts the whole history before every provider request: user and assistant text, tool-call arguments, tool results, bash executions, compaction and branch summaries. Messages are copied, never mutated. Assistant thinking blocks are left byte-identical because providers sign them.
tool_call Restores tokens in tool arguments to the real values.
message_end Restores tokens in the assistant reply so it is stored as plaintext.
compaction / branch summary Both call the model directly, so the extension runs them itself with redacted input. If that is impossible (no model, auth failure, error) the summary is cancelled rather than falling back to plaintext.

While a reply is streaming you may briefly see tokens; they are replaced with the real values when the message ends.

How tokens work: the session vault

Each session has a vault that maps every sensitive value to a token such as [EMAIL_3#k7q2]:

  • The same value always gets the same token, and the number per label only goes up, so the model sees consistent identities across turns.
  • k7q2 is a random per-session nonce. Text that merely looks like a token (for example [EMAIL_1] in a file) is never restored.
  • Restore tolerates the ways models mangle tokens: missing brackets, lower case and extra spaces (email_3#k7q2, [ EMAIL_3 # k7q2 ]). Tokens not in the vault are left unchanged.
  • Rules with a custom mask are one-way and are not restored.

Security model

This extension protects what reaches the model, not what is on disk.

Data In the session file Sent to the LLM
Your input, tool output redacted (tokens) tokens
Assistant replies, tool-call arguments, compaction and branch summaries plaintext (restored) re-redacted to tokens by context
Vault mapping pii-vault custom entries with token and original never

Session files contain the original values, both in the pii-vault entries and in assistant replies. Protect them like any other file holding sensitive data.

Detection is model- and pattern-based and can miss things or over-redact. Treat it as a strong safety net, not a guarantee.

Development

Requires Node.js 22 or later.

npm install
npm run typecheck
npm test

Load your working copy into Pi with pi -e ., or install it with pi install . to keep it loaded.

Releasing

Versioning, the changelog and npm publishing are handled by Changesets and .github/workflows/publish.yml.

  1. In any PR that changes behavior, run npx changeset, pick the bump type (patch, minor or major), describe the change for users, and commit the generated file in .changeset/.
  2. When the PR is merged, the workflow opens or updates a Version Packages PR that bumps package.json and writes CHANGELOG.md.
  3. Merging the Version Packages PR publishes @chrisdoc/pi-pii-redact to npm with provenance and creates a git tag and GitHub release.

Publishing uses npm trusted publishing (OIDC): npm trusts the publish.yml workflow in chrisdoc/pi-pii-redact, so there is no npm token in the repository. The workflow needs "Allow GitHub Actions to create and approve pull requests" enabled under Settings → Actions → General to open the Version Packages PR.

License

MIT