#1569 Phase 1 discovery (2026-05-02) found six historical credential exposures in molecule-core git history. All confirmed dead — but the reason they got committed in the first place was that the local pre-commit hook had two gaps that the canonical CI gate (and the runtime's hook) didn't: 1. **Pattern set was incomplete.** Local hook checked `sk-ant-|sk-proj-|ghp_|gho_|AKIA|mol_pk_|cfut_` — missing `ghs_*`, `ghu_*`, `ghr_*`, `github_pat_*`, `sk-svcacct-`, `sk-cp-`, `xox[baprs]-`, `ASIA*`. The historical leaks were 5× `ghs_*` (App installation tokens) + 1× `github_pat_*` — none of which the local hook would have caught even if it ran. 2. **`*.md` and `docs/` were skip-listed.** The leaked tokens lived in `tick-reflections-temp.md`, `qa-audit-2026-04-21.md`, and `docs/incidents/INCIDENT_LOG.md` — exactly the file types the skip-list excluded. The hook ran and silently passed. This commit: - Replaces the local hook's hard-coded inline regex with the canonical 13-pattern array (byte-aligned with `.github/workflows/secret-scan.yml` and the workspace runtime's `pre-commit-checks.sh`). - Removes the `\.md$|docs/` skip — keeps only binary, lockfile, and hook-self exclusions. - Adds the local hook to `lint_secret_pattern_drift.py` as an in-repo consumer (read-from-disk, no network — the hook lives in the same checkout the lint runs against). Drift now fails the lint when canonical changes without the local hook updating in lockstep. - Adds `.githooks/pre-commit` to the drift-lint workflow's path filter so consumer-side edits also trigger the lint. - Adopts the canonical's "don't echo the matched value" defense (the prior version would have round-tripped a leaked credential into scrollback / CI logs). Verified: `python3 .github/scripts/lint_secret_pattern_drift.py` reports both consumers aligned at 13 patterns. The hook's existing six other gates (canvas 'use client', dark theme, SQL injection, go-build, etc.) are untouched. Companion change (already applied via API, no diff here): `Scan diff for credential-shaped strings` is now in the required-checks list on both `staging` and `main` branch protection — was previously a soft gate (workflow ran, exited 1, but didn't block merge). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
59 lines
2.1 KiB
YAML
59 lines
2.1 KiB
YAML
name: SECRET_PATTERNS drift lint
|
|
|
|
# Detects when the canonical SECRET_PATTERNS array in
|
|
# .github/workflows/secret-scan.yml diverges from known consumer
|
|
# mirrors (workspace-runtime's bundled pre-commit hook today; more
|
|
# can be added as the consumer set grows).
|
|
#
|
|
# Why this exists: every side that scans for credentials has its own
|
|
# copy of the pattern list. They drift — most recently the runtime
|
|
# hook lagged the canonical by one pattern (sk-cp- / MiniMax F1088),
|
|
# so a developer's local pre-commit would let a sk-cp- token through
|
|
# while the org-wide CI scan would refuse it. The cost of that drift
|
|
# is dev confusion + delayed feedback; the fix is automated detection.
|
|
#
|
|
# Triggers:
|
|
# - schedule: daily 05:00 UTC. Catches drift introduced by edits
|
|
# to a consumer copy that didn't update canonical here.
|
|
# - push to main/staging where the canonical or this lint changed:
|
|
# catches the inverse — canonical updated but consumers not yet
|
|
# bumped. The lint will fail the push; that's intentional, the
|
|
# person editing canonical is the right person to also update
|
|
# the consumer.
|
|
# - workflow_dispatch: ad-hoc operator runs.
|
|
|
|
on:
|
|
schedule:
|
|
# 05:00 UTC = 22:00 PT / 01:00 ET. Quiet hours so a failure
|
|
# email lands when humans are starting their day, not
|
|
# interrupting it.
|
|
- cron: "0 5 * * *"
|
|
push:
|
|
branches: [main, staging]
|
|
paths:
|
|
- ".github/workflows/secret-scan.yml"
|
|
- ".github/workflows/secret-pattern-drift.yml"
|
|
- ".github/scripts/lint_secret_pattern_drift.py"
|
|
- ".githooks/pre-commit"
|
|
workflow_dispatch:
|
|
|
|
# GITHUB_TOKEN scoped to read-only. The lint only does git checkout
|
|
# + HTTPS GETs to public consumer files; no writes to anything.
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
lint:
|
|
name: Detect SECRET_PATTERNS drift
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
with:
|
|
python-version: "3.11"
|
|
|
|
- name: Run drift lint
|
|
run: python3 .github/scripts/lint_secret_pattern_drift.py
|