Commit graph

2 commits

Author SHA1 Message Date
Parfii-bot
8473b4ae80 fix(hooks+install): disk-reclaim Guard 3 + secrets per-line + sha256 fail-closed
Three independent shell hardening fixes from Opus Shell + Sonnet Shell audits.

1. disk-reclaim.sh Guard 3 — protect branches without upstream tracking (HIGH)
   File: hooks/disk-reclaim.sh:88-101
   Bug: when a worktree branch has no upstream tracking ref, `git log @{u}..`
   exited non-zero and `unpushed=""` (empty). The check
   `[ -n "$unpushed" ] && [ "$unpushed" != "0" ]` evaluated FALSE, so the
   worktree fell through Guard 3 and was eligible for mtime-based pruning.
   Local-only branches with committed work were silently deleted.

   Fix: explicit two-branch logic. Run `git rev-parse --abbrev-ref @{u}` first;
   only run the unpushed-count check if upstream exists. If no upstream, log
   SKIP[no-upstream] and `continue` conservatively. New
   `worktrees_skip_unpushed` counter increments in both unpushed paths.

2. secrets-pre-guard.sh — placeholder allowlist scope-narrow (MEDIUM)
   File: hooks/secrets-pre-guard.sh:43-103
   Bug: word "placeholder" anywhere in content disabled all secret-pattern
   scanning for that whole Write. Allowlist was too broad — a doc with the
   word "placeholder" in its prose could mask a real sk-ant- token elsewhere.

   Fix: replaced global early-exit with per-line awk scan. New scan_pattern()
   helper walks content line-by-line; each line matching a secret regex is
   allowed ONLY if the SAME line also matches ALLOWLIST_RE. Doc prose can no
   longer mask cross-line secrets. Added `dummy[_-]?(key|token|secret)` to
   allowlist for legitimate test fixtures.

3. lib-rust-prebuild.sh — sha256 fail-closed (HIGH supply-chain)
   File: install/lib-rust-prebuild.sh:75-88
   Bug: when ${url}.sha256 404'd, installer printed WARNING and proceeded with
   unverified tarball. A compromised github release uploader could ship a
   malicious tarball, omit .sha256, and the installer would extract it into
   ~/.cargo/bin/.

   Fix: missing .sha256 → ERROR + abort. Path A install fails → falls back to
   Path B (cargo build from source). Override via KEI_ALLOW_UNVERIFIED_TARBALL=1
   (visible per-call, intentional friction).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 15:37:57 +08:00
Parfii-bot
85a61d7253 fix(hooks): post-audit hook chain hardening + 4 new defensive hooks
Hook chain repairs (Group A):
- alignment-check.sh: read .prompt (was .user_prompt) — hook was dead
- block-dangerous.sh: jq instead of inline interpreter (RULE 0.2 + fail-open fix)
- destructive-guard.sh: explicit INPUT=cat + jq guard + exit 0 — was silent no-op
- numeric-claims-guard.sh: exit 1 -> exit 2 (Claude Code spec — was non-blocking)
                          comments updated 0.17 -> 0.18 (env var name kept)
- no-downgrade.sh: removed (?i) PCRE syntax — POSIX ERE matched literal text
- task-timer.sh: jq -nc instead of bare printf — JSON injection on quotes/backslashes
                 in description was corrupting RULE 0.18 evidence journal
- check-error-patterns.sh: replaced with no-op stub — had hardcoded /Users/denis/...
                            PATH LEAK in public kit, plus inline interpreter use
- post-commit-audit.sh: added trailing exit 0 — grep return code was hook exit code
- citation-verify.sh: ALLOW_REGEX accepts HOOK-BYPASS marker — bypass was documented
                       but never matched
- settings-snippet.json: agent-stub-scan moved PreToolUse:Agent -> PostToolUse:Agent
                          (RULE 0.16 enforcement was firing before transcript existed)
- check-error-patterns hook removed from settings-snippet.json

New defensive hooks (Group H):
- no-github-push.sh: PreToolUse:Bash hard deny on github.com push/create/sync/remote-add
                      (RULE 0.1 — patent IP protection; was missing from public kit)
- secrets-pre-guard.sh: PreToolUse:Edit|Write — token-pattern scan with allowlist (RULE 0.8)
- chat-numeric-prewarn.sh: UserPromptSubmit reminder when prompt mentions time/cost
                            (RULE 0.18 chat extension)
- chat-numeric-postflag.sh: Stop event scans last assistant message for naked numerics
                             without REAL/FROM-JOURNAL/ESTIMATE-HTC markers

Source: full Sonnet test-retest audit 2026-05-02 (3 parallel waves of 6 agents each)
identified hook chain bugs as HIGH severity in all 3 runs independently.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 21:38:47 +08:00