-
Notifications
You must be signed in to change notification settings - Fork 0
Security Model
This library is assembled partly from private working notes, so leakage is the failure mode it is designed against rather than one it hopes to avoid.
Three independent places, because a gate with one chokepoint is a gate with one bypass:
-
npm run build/npm run check— locally - the
pre-commitandcommit-msggit hooks - GitHub Actions, on every push and pull request
Pattern class — private keys, PEM blocks, seed phrases, JWTs, and the key shapes of the
common providers; any .env file; any *_KEY= / *_SECRET= / *_TOKEN= carrying a real value;
local filesystem paths; email addresses; phone numbers; street addresses.
Denylist class, in two layers:
-
data/denylist.public.json— operational literals, committed, always on. This is why the gate works for forks and outside contributors with no secret to configure. -
scripts/denylist.local.json— personal literals. Gitignored, never committed, optionally supplied to CI throughSCRUB_DENYLIST.
Publishing a hash of the personal layer was considered and rejected: for a low-entropy string like a home address, a hash is a checkable oracle rather than a protection.
Address class — wallet addresses are default-deny. Any 0x-prefixed 40-hex string fails
unless it is listed in data/public-addresses.allow.json
with a reason. A leak by omission is the failure an allowlist prevents and a denylist does not.
Commit messages are scanned too — message body and author line. The body is a public surface with no other gate, and the contributing guide actively asks for evidence prose there, which is exactly the text most likely to carry a path or a name.
node scripts/canary.mjsPlants a fabricated secret of every class into _inbox/, runs the scan, prints CAUGHT or MISSED
per class, removes the file, and confirms the tree is clean afterwards. Any MISSED line is a hole
and a bug worth reporting.
The scanner scans its own source too. Inline exclusion markers cannot disable the gate. Binary artifacts still require manual review; a clean text scan is not a complete privacy review.
_inbox/drafts/<slug>/ gitignored staging
↓ scrub hard fail; nothing moves while red
↓ a human or model writes the verdict ← cannot be automated
↓ promote.mjs the only door
ideas/<category>/<slug>/ public
promote.mjs refuses unless the draft scrubs clean, carries no leftover TODO or import-note
block, and passes the full validator. Files under code/ are copied and scanned one at a time,
never as a directory, and any failure rolls the whole promotion back.
Open an issue with only the file path. Do not paste the content and do not describe what it is.
Reference
Contributing