Skip to main content

Credential leak guard must require a word boundary or it blocks a filename containing "sk-

lesson · created 2026-09-21 · actor hermes-cron · confidence high · status active tags: knowledgelayer sync guard regex false-positive

Observed 2026-09-21 05:45 AEST on Zappo (macbook-pro-3). The daily knowledgelayer-sync-daily job failed with kl sync: BLOCKED — credential-shaped string tracked in repo; scrub before push.

Cause: the leak guard regex matched sk- anywhere in the text. The lesson filename lessons/2026-09-11-disk-full-broke-cron-ledger-monitor-watched-sealed-volume.md contains the substring isk-full... (from disk-full), which satisfies sk-[A-Za-z0-9]{20,} because isk-full plus the rest of the filename runs past 20 characters. No credential was present. The guard looked only at tracked *.md content, so one referenced path poisoned the whole sync.

The fix in both guard locations (~/.hermes/bin/kl sync step, tools/kl.py LEAK) adds a non-key-character boundary: bash ERE uses (^|[^A-Za-z0-9_-]), Python uses (?<![A-Za-z0-9_-]). Both keep the remaining alternatives unchanged.

Rule: a substring-based secret scanner must anchor on a boundary. Without one, ordinary prose (disk-full, task-force, risk-mitigation) trips it and the guard stops the pipeline it is meant to protect.

Verification after the fix: unit cases pass (sk-proj-..., legacy sk-, ghp_, AKIA, PEM header, JWT each match; the lesson filename does not). A staged probe file containing a real sk-proj- key was still blocked. kl sync then ran clean and pushed 5b6ed14; local and origin/main matched at 0 ahead / 0 behind.

Note: the stale second clone at ~/Projects/knowledgelayer (HEAD 5fb5499) still holds the unfixed kl.py. It is not on the sync path; fix or remove it if it is ever revived.

2026-10-04 recurrence: the same bug in the publish guard​

The fix above was applied to the two sync guards and never to the publish guard, so the same false positive blocked the website publish for another two weeks.

Observed 2026-10-04 21:26 AEST, a manual run of publish-site.sh on Zappo. It failed with Error: Leak guard: credential-shaped string in lessons/2026-09-20-weekly-disk-hygiene-...md (/sk-[A-Za-z0-9_-]\{20,}/). The match was once again a filename slice: the referenced lesson path contains disk-full, and its isk-full... run satisfies the pattern for 55 characters. Four locations in the canonical tree tripped it: two index.json path entries and two prose references to the same lesson.

Cause of the recurrence: the pattern lived in ai-hub/scripts/sync-knowledgelayer.mjs (LEAK_PATTERNS, line 35), a separate implementation from tools/kl.py, so fixing the Python guard did nothing for the publish path. A shared bug needs a fix in every implementation, not the first one found.

Fix 2026-10-04: LEAK_PATTERNS entries are now built with a leading (?<![A-Za-z0-9_-]) boundary, matching the Python guard. AKIA additionally requires (?<![0-9A-Z]) because its character class overlaps its own prefix, so a bare lookbehind would never match it. Verified: node --check passes, the real index.json no longer trips the guard, sk-proj-..., ghp_..., AKIA... and AIza... still match, a dry sync-knowledgelayer.mjs run exits 0 over 107 files, and the repo's 29 node tests pass.

Caveat found while writing this note: a boundary-anchored pattern still false-positives when the prose wraps a filename across a line break, because the newline supplies the boundary the guard wants. This note tripped kl.py's guard for exactly that reason before the wording changed. Keep a long path on one line, or describe the matching substring instead of quoting the path.

Rule: when a leak-guard or scan pattern exists in more than one implementation, fix every copy and record where each one lives. A single-implementation fix leaves the others blocking silently.


Sources: ~/.hermes/bin/kl · ~/.hermes/knowledgelayer/tools/kl.py · kl sync run 2026-09-21 05:45 AEST