From c981fa22970176055f1f072ea58f75a3710fdc3d Mon Sep 17 00:00:00 2001 From: SandObserver <260779319+SandObserver@users.noreply.github.com> Date: Sat, 22 Aug 2026 19:24:47 -0400 Subject: [PATCH] Chore: gate credentials and private addresses in the check script Adds a secrets check over the files this repository authors, covering token shapes for several providers, private key blocks, JWTs, and RFC 1918 addresses. Documented examples in prose are allowed; stub payloads and page sources are not. Skips binary files in the hygiene scan. Byte sequences in images were matching the word list and would have failed CI for no reason. --- scripts/check-dist.mjs | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/scripts/check-dist.mjs b/scripts/check-dist.mjs index 5c826ce..ee4175b 100644 --- a/scripts/check-dist.mjs +++ b/scripts/check-dist.mjs @@ -60,9 +60,40 @@ const SELF = 'scripts/check-dist.mjs'; const files = [ ...SRC_ROOTS.flatMap((r) => globSync(`${r}/**/*`)), ...ROOT_FILES.filter(existsSync), -].filter((f) => f !== SELF && statSync(f).isFile() && statSync(f).size < 3_000_000); +] + .filter((f) => f !== SELF && statSync(f).isFile() && statSync(f).size < 3_000_000) + /* Binary bytes produce meaningless matches. */ + .filter((f) => !/\.(png|jpe?g|ico|woff2?)$/i.test(f)); report('hygiene', files.filter((f) => BANNED.test(read(f)))); +/* Nothing authored here may carry a credential or a real private address. + Scoped to what this repository writes. public/js and public/widgets are + verbatim copies of the application and carry its own placeholders. */ +const SECRET = [ + [/(gh[pousr]_|github_pat_)[A-Za-z0-9_]{20,}/, 'GitHub token'], + [/\bsk-[A-Za-z0-9]{20,}/, 'API key'], + [/\bAKIA[0-9A-Z]{16}\b/, 'AWS key id'], + [/\bAIza[0-9A-Za-z_-]{20,}/, 'Google API key'], + [/\bxox[baprs]-[A-Za-z0-9-]{10,}/, 'Slack token'], + [/-----BEGIN [A-Z ]*PRIVATE KEY-----/, 'private key'], + [/\beyJ[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\./, 'JWT'], + [/\b(?:10|127)\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/, 'private IP'], + [/\b192\.168\.\d{1,3}\.\d{1,3}\b/, 'private IP'], + [/\b172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}\b/, 'private IP'], +]; +const authored = [...globSync('src/**/*'), ...globSync('public/api/**/*')] + .filter((f) => statSync(f).isFile() && !/\.(png|jpe?g|ico|woff2?)$/i.test(f)); +const secretHits = []; +for (const f of authored) { + const t = read(f); + for (const [re, label] of SECRET) { + const m = t.match(re); + /* Documented examples are allowed, and only in prose. */ + if (m && !(label === 'private IP' && f.endsWith('.md'))) secretHits.push(`${f}: ${label} ${m[0]}`); + } +} +report('secrets', secretHits); + /* House style. */ report('style', files.filter((f) => f.startsWith('src') && read(f).includes('—')));