pii-firewall
v0.2.6
Published
Open-source PII firewall for LLM apps. Detect, anonymize and rehydrate sensitive data before it reaches any LLM provider.
Maintainers
Readme
pii-firewall
Open-source PII firewall for LLM apps. Detect, anonymize, and rehydrate sensitive data before it reaches any LLM provider — with zero runtime dependencies.
Installation
npm install pii-firewallQuick start
import { PrivacyFirewallSDK } from "pii-firewall";
const sdk = PrivacyFirewallSDK.create({ domain: "generic" });
const context = {
tenant_id: "acme",
case_id: "support-123",
thread_id: "thread-1",
actor_id: "agent-1",
};
// 1. Anonymize before sending to the LLM
const { sanitizedText, trace } = sdk.anonymizeText(
"Call Alice at [email protected] or 555-123-4567",
context,
);
// sanitizedText → "Call [PERSON_001] at [EMAIL_001] or [PHONE_NUMBER_001]"
// 2. Send sanitizedText to your LLM …
const modelReply = "[PERSON_001] has been contacted at [EMAIL_001]";
// 3. Rehydrate the LLM response
const finalReply = sdk.rehydrateText(modelReply, context);
// finalReply → "Alice has been contacted at [email protected]"Secure LLM call (one-liner)
import { PrivacyFirewallSDK, MockLLMClient } from "pii-firewall";
const sdk = PrivacyFirewallSDK.create({ domain: "generic" });
const llm = new MockLLMClient(); // replace with your real client
const result = await sdk.secureCall(
"My SSN is 123-45-6789, what should I do?",
context,
llm,
);
console.log(result.sanitizedText); // sent to LLM → "My SSN is [SSN_001], what should I do?"
console.log(result.finalText); // back to user → original values restoredDomain profiles
Choose a built-in profile or create a custom one:
// Built-in: "generic" | "healthcare" | "finance" | "legal"
const sdk = PrivacyFirewallSDK.create({ domain: "healthcare" });
// Custom profile
import { createCustomProfile, getPresetProfile, DispositionAction, createDisposition } from "pii-firewall";
const myProfile = createCustomProfile("my-app", {
baseProfile: getPresetProfile("generic"),
dispositions: {
EMPLOYEE_ID: createDisposition({
entityType: "EMPLOYEE_ID",
action: DispositionAction.PSEUDONYMIZE,
}),
},
});
const sdk = PrivacyFirewallSDK.create({ profile: myProfile });Anonymize nested payloads
Sanitize entire JSON request bodies before sending to an LLM API:
const payload = {
messages: [
{ role: "user", content: "My email is [email protected]" },
{ role: "user", content: "My card is 4111111111111111" },
],
};
const sanitized = sdk.anonymizePayload(payload, context);
const restored = sdk.rehydratePayload(sanitized, context);Streaming support
for await (const chunk of sdk.secureCallStream(prompt, context, llmClient)) {
process.stdout.write(chunk); // tokens are rehydrated on the fly
}Custom patterns
Add your own regex patterns at runtime:
import { createFirewall, createPattern } from "pii-firewall";
const fw = createFirewall({ domain: "generic" });
// Via helper (also registers disposition automatically)
fw.addCustomRegex({
entityType: "EMPLOYEE_ID",
regex: "\\bEMP-\\d{6}\\b",
locales: ["US"],
dispositionAction: "pseudonymize",
});
// Or via full EntityPattern object
fw.addCustomPattern(
createPattern({ entityType: "BADGE_ID", locale: "GLOBAL", pattern: /BADGE-\d{4}/ })
);Supported PII types
| Entity type | Example |
|---|---|
| EMAIL | [email protected] |
| PHONE_NUMBER | +1 555-123-4567 |
| NATIONAL_ID | 12345678Z (DNI), RSSMRA80A01H501U (Codice Fiscale) |
| SSN | 123-45-6789 |
| IBAN | ES9121000418450200051332 |
| CREDIT_CARD | 4111 1111 1111 1111 |
| IP_ADDRESS | 192.168.1.1, 2001:db8::1 |
| URL | https://example.com |
| PASSPORT | — |
| DRIVERS_LICENSE | — |
| POSTAL_CODE | 28001, 10115, 75001 |
| TAX_ID | NIF, EIN, Steuer-ID |
| DATE / AGE | generalized to year / decade |
| MAC_ADDRESS | 00:1A:2B:3C:4D:5E |
| DOI / PMID | academic references |
Supported languages & locales
| Language | Locale patterns | |---|---| | English | US (SSN, ZIP, DL, MRN, …) | | Spanish | ES (DNI, NIE, IBAN, …) | | French | FR (INSEE, IBAN, …) | | German | DE (Steuer-ID, IBAN, …) | | Italian | IT (Codice Fiscale, Partita IVA, …) | | Portuguese | PT (NIF, CPF, …) |
Language is auto-detected from the input text, or you can set it explicitly:
const sdk = PrivacyFirewallSDK.create({ manualLanguage: "es" });Anonymization actions
| Action | Description |
|---|---|
| PSEUDONYMIZE | Replace with reversible token [TYPE_001] |
| GENERALIZE | Reduce precision (age → decade, date → year) |
| MASK | Partially obscure (****1234) |
| HASH | Replace with SHA-256 hash token |
| REDACT | Remove completely |
| KEEP | Leave unchanged (used in domain profiles) |
Forget / right to erasure
sdk.forget(tenant_id, case_id, thread_id);
// Removes all vault mappings for that conversationZero runtime dependencies
This package uses only Node.js built-ins (crypto). No external dependencies are required.
License
Apache-2.0
