secrets.sh never runs its private-key pattern and verify never scans dist #235

Closed
opened 2026-09-10 04:13:36 -05:00 by null · 1 comment
Owner

Seen at a25077d (v0.9.5) and 7415e19.

What is true now, in scripts/secrets.sh:

  • grep -nEI "$pattern" (line 320) and grep -oEI "$pattern" (line 335) have no -e, so the private-key pattern, which starts with dashes, is read as an option. grep exits 2 and 2>/dev/null hides it. A staged private key passes the pre-commit hook. Proven on 2026-09-10 in a scratch repository.
  • The 2026-08-29 pattern, committed as-is in 7415e19, flags two comment lines (scripts/secrets.sh:29 and scripts/check-env.sh:61), so bash scripts/secrets.sh --tracked exits 1, npm run verify fails, and npm run release dies after bumping package.json, package-lock.json and the Dockerfile. The comment above the pattern (lines 170-172) no longer describes it.
  • verify never scans dist/, although docs/security/SECURITY_CHECKLIST.md lists --built dist/ as a release check.

What it costs. The one guard between a credential and a pushed commit silently misses private keys, and the release gate is red.

What to do. -e "$pattern" at both calls; treat a grep exit 2 as "could not scan" (exit 2), never as clean; quote the two comment examples; correct the comment; add --built dist/ to scripts/verify.d/20-secrets. Docs: docs/security/SECURITY.md:52, a SECURITY_CHECKLIST.md row, and a docs/architecture/GUARDS.md rule that a matcher's 2>/dev/null turns "could not run" into "found nothing".

Trap. Never write a literal private-key header or AWS key id into a tracked file, including the dev log; the fixed scanner flags it.

Verify: in a scratch repository a staged private-key header, a bare API_KEY= value and an exported secret each exit 1, PASSWORD=${VAR} and a delete-only commit exit 0, bash scripts/secrets.sh --tracked exits 0, and bash scripts/verify.sh --only secrets runs the --built dist/ scan.

Seen at a25077d (v0.9.5) and 7415e19. **What is true now,** in `scripts/secrets.sh`: - `grep -nEI "$pattern"` (line 320) and `grep -oEI "$pattern"` (line 335) have no `-e`, so the private-key pattern, which starts with dashes, is read as an option. grep exits 2 and `2>/dev/null` hides it. A staged private key passes the pre-commit hook. Proven on 2026-09-10 in a scratch repository. - The 2026-08-29 pattern, committed as-is in 7415e19, flags two comment lines (`scripts/secrets.sh:29` and `scripts/check-env.sh:61`), so `bash scripts/secrets.sh --tracked` exits 1, `npm run verify` fails, and `npm run release` dies after bumping `package.json`, `package-lock.json` and the Dockerfile. The comment above the pattern (lines 170-172) no longer describes it. - verify never scans `dist/`, although `docs/security/SECURITY_CHECKLIST.md` lists `--built dist/` as a release check. **What it costs.** The one guard between a credential and a pushed commit silently misses private keys, and the release gate is red. **What to do.** `-e "$pattern"` at both calls; treat a grep exit 2 as "could not scan" (exit 2), never as clean; quote the two comment examples; correct the comment; add `--built dist/` to `scripts/verify.d/20-secrets`. Docs: `docs/security/SECURITY.md:52`, a `SECURITY_CHECKLIST.md` row, and a `docs/architecture/GUARDS.md` rule that a matcher's `2>/dev/null` turns "could not run" into "found nothing". **Trap.** Never write a literal private-key header or AWS key id into a tracked file, including the dev log; the fixed scanner flags it. Verify: in a scratch repository a staged private-key header, a bare `API_KEY=` value and an exported secret each exit 1, `PASSWORD=${VAR}` and a delete-only commit exit 0, `bash scripts/secrets.sh --tracked` exits 0, and `bash scripts/verify.sh --only secrets` runs the `--built dist/` scan.
null added this to the Batch 18: Guards and landmines found building Batch 17 milestone 2026-09-10 04:13:36 -05:00
null added the
P1
bug
security
labels 2026-09-10 04:13:36 -05:00
null closed this issue 2026-09-10 04:23:41 -05:00
Author
Owner

Fixed in 26136f4. grep now takes -e at scripts/secrets.sh:320 and :335, every pattern is compiled against empty input before the scan (an unreadable one exits 2), the NAME=value pattern also catches quoted values, and a line that must show a credential shape carries secrets-ok: with a reason. Guard 20-secrets runs --tracked and --built dist/. Proven by mutation in a scratch repository: a staged PEM header, a bare API_KEY=, a quoted API_KEY=, an exported secret and an AWS key id each exit 1; a ${VAR} value, a , an excused line and a delete-only commit each exit 0; a broken pattern exits 2 both with content staged and with none; a key planted in dist/ fails guard 20-secrets alone and is masked in the report. bash scripts/secrets.sh --tracked and --built dist/ both exit 0 on this tree, and npm run verify passes all three guards.

Fixed in 26136f4. grep now takes -e at scripts/secrets.sh:320 and :335, every pattern is compiled against empty input before the scan (an unreadable one exits 2), the NAME=value pattern also catches quoted values, and a line that must show a credential shape carries secrets-ok: with a reason. Guard 20-secrets runs --tracked and --built dist/. Proven by mutation in a scratch repository: a staged PEM header, a bare API_KEY=, a quoted API_KEY=, an exported secret and an AWS key id each exit 1; a ${VAR} value, a <placeholder>, an excused line and a delete-only commit each exit 0; a broken pattern exits 2 both with content staged and with none; a key planted in dist/ fails guard 20-secrets alone and is masked in the report. bash scripts/secrets.sh --tracked and --built dist/ both exit 0 on this tree, and npm run verify passes all three guards.
Sign in to join this conversation.
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: null/Queue-North-Website#235
No description provided.