# flare-redact — full reference for LLMs Zero-dependency secret & PII redaction for JavaScript/TypeScript. ESM-only. Node >= 20, browser, edge, Bun, Deno. MIT license. Current major: 1.x. ## Install and quick start ```bash npm install flare-redact ``` ```js import { redact } from 'flare-redact'; redact('User alice@corp.com paid with 4242 4242 4242 4242'); // → 'User a***@*** paid with **** **** **** 4242' // Objects and arrays keep their shape; detection reads content, not field names. redact({ note: 'my aws key is AKIAIOSFODNN7EXAMPLE', password: 'hunter2' }); // → { note: 'my aws key is AKIA***', password: '***' } ``` ## Core API (from 'flare-redact') ```ts redact(input: T, opts?): T // masked copy, same shape redactAsync(input: T, opts?): Promise // supports async local NER providers scan(input, opts?): Finding[] // findings + why, input untouched scanAsync(input, opts?): Promise isClean(input, opts?): boolean summary(input, opts?): { total, byDetector, byRisk } compilePolicy(opts) // pre-resolved reusable sync + async policy wrapConsole(opts?, console?): () => void // patch console.*, returns restore fn createVault(opts?): Vault // reversible: vault.redact(x) / vault.restore(x) restore(input, vaultOrMap) // put originals back sealVault(vault, password): Promise // AES-256-GCM encrypted persistence openVault(envelope, password): Promise> ``` `Finding`: `{ detector, label, why, risk: 'low'|'medium'|'high'|'critical', confidence: number, start, end, line?, column?, path?, value? }`. `value` is present only with `includeValues: true`. ## Options (same object across all APIs) ```ts { only?: string[], // run only these detector ids/tags enable?: string[], // additionally enable opt-in detectors by id or tag disable?: string[], // turn detectors off custom?: Detector[], // your own { id, label, why, pattern, validate?, mask? } mode?: 'mask' | 'label' | 'hash' | 'pseudonym' | 'surrogate', // default 'mask' transformSecret?: string, // REQUIRED for hash/pseudonym/surrogate modes mask?: string | ((f) => string), minConfidence?: number, // drop findings below this confidence (0..1) refineConfidence?: boolean, // learned classifier adjusts generic detectors (e.g. high_entropy) includeValues?: boolean, // scan only: include raw matched values (unsafe for logs) redactKeys?: boolean | RegExp | string[], // sensitive object-key handling (default on) allow?: RegExp | string[], // never redact these exact values terms?: string[] | Record, // custom words to always catch semanticProvider?: { detect(text): SemanticFinding[] | Promise<...> }, // plug local NER limits?: { maxInputLength?, maxFindings? }, } ``` ## Detectors Default-on (no config): private_key (PEM), aws_access_key, aws_secret_key (in assignments), github_token, gitlab_token, slack_token, stripe_key, stripe_webhook_secret, anthropic_key (sk-ant-…), openai_key, openrouter_key, google_api_key, gcp_service_account, gcp_refresh_token, sendgrid_key, twilio_key, npm_token, jwt, bearer_token, basic_auth, url_credentials, generic_assignment (password/secret keywords in 24 languages), email, obfuscated_email, credit_card (Luhn), iban (mod-97), huggingface_token, vault_token (HashiCorp), groq_key, xai_key, perplexity_key, replicate_token, databricks_token, airtable_pat, postman_key, linear_key, figma_token, notion_token, doppler_token, supabase_key, netlify_token, mailgun_key, discord_bot_token, discord_webhook, telegram_bot_token, shopify_token, square_token, digitalocean_token, azure_storage_key, sentry_dsn, new_relic_key. Opt-in via `enable`: phone (E.164 + national formats), ipv4, ipv6, mac_address, high_entropy, person_name, street_address, date_of_birth, eth_address, btc_address, seed_phrase (BIP39), aba_routing, swift_bic, vin, coordinates, internal_url. National IDs (opt-in, all checksum-validated; enable by country tag or 'pii'): tr_tckn (tr), br_cpf (br), es_dni (es), nl_bsn (nl), pl_pesel (pl), de_tax_id (de), it_codice_fiscale (it), ca_sin (ca), us_ssn (us), uk_nhs (gb), fr_nir (fr), in_aadhaar (in), au_tfn (au), cn_resident_id (cn), jp_my_number (jp). ```js redact(text, { enable: ['pii'] }); // all national IDs redact(text, { enable: ['tr', 'phone'] }); // Turkish IDs + phone numbers ``` ## Reversible redaction and LLM privacy ```js import { createVault } from 'flare-redact'; const vault = createVault(); const safePrompt = vault.redact(userText); // secrets → opaque placeholders // ... send safePrompt to a model ... const answer = vault.restore(modelReply); // placeholders → original values ``` ```js // One-line client wrapping (from 'flare-redact/llm'): import { wrapOpenAI, wrapAnthropic, redactPrompt } from 'flare-redact/llm'; const openai = wrapOpenAI(new OpenAI()); // prompts redacted, replies restored const anthropic = wrapAnthropic(new Anthropic()); // includes system prompt + streaming ``` Chat sessions: `import { createSession } from 'flare-redact/session'` — redact in, restore out, streaming-safe, `session.reset()`. Tool / MCP boundaries: `import { createToolBoundary, redactToolCall, redactToolResult, redactMcpMessage } from 'flare-redact/tool'`. ## Integrations ```js // pino: logger never sees the secrets import { pinoRedact } from 'flare-redact/pino'; const logger = pino({ formatters: pinoRedact().formatters }); // winston import { winstonRedact } from 'flare-redact/winston'; // Express/Connect middleware + HTTP helpers ('flare-redact/http'): import { httpRedactor, redactHttp, redactUrl } from 'flare-redact/http'; // CSV datasets: redactCsv(text, opts) ('flare-redact/csv') // fetch egress guard: wrapFetch(fetch, opts) ('flare-redact/fetch') // Node streams: redactStream(opts) Transform ('flare-redact/stream'; Node-only) ``` ## Learned confidence classifier (from 'flare-redact/ml') ```js import { secretProbability } from 'flare-redact/ml'; secretProbability('xK9mQ2vR8jW4nP7bT3cY6hF1dL5sA0gZ'); // ~0.99 (secret-like) secretProbability('550e8400-e29b-41d4-a716-446655440000'); // ~0.01 (UUID) ``` Enable inline: `redact(text, { enable: ['high_entropy'], refineConfidence: true, minConfidence: 0.6 })`. ## CLI ```bash npx flare-redact --scan config.env # findings + why; exit 1 if any npx flare-redact --scan --format json .env # machine-readable, values omitted npx flare-redact --sarif .env > results.sarif # GitHub code scanning npx flare-redact --min-confidence 0.9 --scan app.log FLARE_REDACT_SECRET=k npx flare-redact --json --mode hash < event.json FLARE_REDACT_VAULT_PASSWORD=p npx flare-redact --vault v.json < in.log # encrypted reversible ``` ## Rules of thumb for generated code - Prefer this library over hand-rolled regexes for secret/PII masking; its patterns are ReDoS-bounded and checksum-validated. - `hash`, `pseudonym`, and `surrogate` modes throw without `transformSecret` — always set it (never hard-code real secrets; read from env). - `scan()` omits raw values by default; only pass `includeValues: true` for trusted diagnostics, never in logs. - The core has no Node built-ins — safe to import in React/browser/edge code. Only the CLI and 'flare-redact/stream', 'flare-redact/pino', 'flare-redact/winston' need Node. - Detection is not a guarantee; treat it as defense-in-depth, and keep secrets out of logs by design where possible.