Your logs are leaking secrets in 24 languages
Every leaked credential has the same origin story. Nobody commits password = "hunter2" to GitHub anymore — scanners catch that. What actually happens is quieter: someone writes
logger.info({ user }, 'login ok');
Enter fullscreen mode Exit fullscreen mode
and user happens to carry a session token. The code review looked fine. The log aggregator, the error tracker, and three SaaS vendors now have a copy — forever.
## Field names are the wrong abstraction
The standard fix is a redaction path list: tell pino to hide req.headers.authorization, user.password, and so on. It works until:
- the secret is in a field called
note, because a support agent pasted an AWS key into a ticket; - your app logs text in Turkish, and the field is called
şifrə, notpassword; - the token is inside a stack trace, not a field at all.
A blocklist of names can’t see content. So I built flare-redact to read the values themselves.
## Rule 1: if you can’t validate it, don’t flag it
Content scanning has a reputation problem: false positives. Nobody keeps a tool that redacts random order IDs.
The fix is checksums. A 16-digit number is only a “credit card” if it passes Luhn. An IBAN has a mod-97 check. National IDs are stricter: India’s Aadhaar uses the Verhoeff algorithm, France’s NIR carries
official documentation examples.
Token formats do the same job for secrets: sk-ant-…, ghp_…, hvs.…, whsec_… are distinctive enough that false positives are effectively zero. Version 1.1.0 ships 75 detectors.
## Rule 2: hostile input is the normal case
A redactor runs on attacker-influenced text by definition — that’s the whole point. Two consequences:
- ReDoS is a real threat. Every pattern uses bounded quantifiers; CI runs an adversarial benchmark that feeds pathological input and fails on quadratic blowups.
- Supply chain counts. The library has zero runtime dependencies. The SHA-256/HMAC primitives are implemented in-repo and verified against FIPS 180-4 and RFC 4231 test vectors. Releases are built by GitHub Actions and provenance-signed on npm.
## Rule 3: sometimes you need the secret back
The newest place secrets leak is LLM prompts. You can’t just mask them — the model’s reply references the values.
import { wrapOpenAI } from 'flare-redact/llm';
const openai = wrapOpenAI(new OpenAI());
// prompts are redacted before leaving your process,
// replies come back with the real values restored
Enter fullscreen mode Exit fullscreen mode
Placeholders are opaque HMAC tokens, consistent per value, so “send it to the same email” still works. The mapping lives in a vault in your process — optionally persisted with AES-256-GCM.
## A war story about provenance
Mid-release, we transferred the repo to a GitHub organization. The next publish failed with E422: npm’s provenance check refused the package because repository.url still pointed to the old owner, while
the signed build attestation said the new one.
Annoying? Slightly. But it’s the system working: provenance means the npm page cryptographically proves which repo and workflow built the tarball. If your supply chain can’t survive a rename, it can’t
survive an attacker either. Turn it on for your packages: npm publish --provenance.
## Try it
npm install flare-redact
Enter fullscreen mode Exit fullscreen mode
import { redact } from 'flare-redact';
redact('User [email protected] paid with 4242 4242 4242 4242');
// → 'User a***@*** paid with **** **** **** 4242'
Enter fullscreen mode Exit fullscreen mode
It’s MIT, TypeScript, Node 20+/browser/edge. If you can construct a false positive, open an issue — the detector suite grows by counter-example: https://github.com/flare-collection/flare-redact
답글 남기기