KeiSeiKit-1.0/hooks/no-github-push.sh
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

86 lines
2.7 KiB
Bash
Executable file

#!/bin/sh
# no-github-push.sh — PreToolUse:Bash hard deny (RULE 0.1 NO GITHUB PUSH)
#
# Blocks any Bash command that would push code to github.com.
# KeiTech portfolio contains unfiled patent IP — a public push destroys
# priority date and trade secrets. Irrecoverable.
#
# Exit codes:
# 0 = pass (command is safe)
# 2 = block (Claude Code aborts the tool call)
#
# Bypass: set KEI_NO_GITHUB_PUSH_BYPASS=1 in the calling environment.
# Even with bypass, the rule is logged to stderr.
set -u
# Bypass check (must be explicit env, not embedded in command string)
if [ "${KEI_NO_GITHUB_PUSH_BYPASS:-0}" = "1" ]; then
printf '[no-github-push] BYPASS active (KEI_NO_GITHUB_PUSH_BYPASS=1). Proceeding.\n' >&2
exit 0
fi
# jq is required to parse the Claude Code hook input
if ! command -v jq > /dev/null 2>&1; then
exit 0
fi
INPUT=$(cat)
COMMAND=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$COMMAND" ] && exit 0
# --- Pattern matching -------------------------------------------------------
# Match any of the forbidden surfaces (case-sensitive; github URLs are
# always lowercase in practice, but we anchor on the protocol/domain).
BLOCKED=0
# git push to github.com (HTTPS or SSH)
if printf '%s' "$COMMAND" | grep -qE 'git[[:space:]]+push[^|&;]*github\.com'; then
BLOCKED=1
fi
# git push to SSH shorthand git@github.com
if [ "$BLOCKED" -eq 0 ] && \
printf '%s' "$COMMAND" | grep -qE 'git[[:space:]]+push[^|&;]*git@github\.com'; then
BLOCKED=1
fi
# gh repo create (any visibility — creating a public repo leaks IP by default)
if [ "$BLOCKED" -eq 0 ] && \
printf '%s' "$COMMAND" | grep -qE 'gh[[:space:]]+repo[[:space:]]+create'; then
BLOCKED=1
fi
# gh repo sync (pushes local state to remote)
if [ "$BLOCKED" -eq 0 ] && \
printf '%s' "$COMMAND" | grep -qE 'gh[[:space:]]+repo[[:space:]]+sync'; then
BLOCKED=1
fi
# git remote add/set-url pointing at github.com
if [ "$BLOCKED" -eq 0 ] && \
printf '%s' "$COMMAND" | grep -qE 'git[[:space:]]+remote[[:space:]]+(add|set-url)[^|&;]*github\.com'; then
BLOCKED=1
fi
[ "$BLOCKED" -eq 0 ] && exit 0
# --- Block ------------------------------------------------------------------
cat >&2 <<'EOF'
[no-github-push] BLOCK — RULE 0.1 NO GITHUB PUSH
KeiTech portfolio contains unfiled patent IP. Public push destroys
priority date + trade secrets. Irrecoverable.
Use a private remote instead (Forgejo, Gitea, self-hosted):
git remote set-url origin ssh://git@<private-host>/<user>/<repo>.git
git push origin <branch>
Bypass (visible, per-call):
Set env KEI_NO_GITHUB_PUSH_BYPASS=1 before the command.
You must also add confirmation phrase: "yes, push patent code to github"
+ "confirm publication" in the session turn.
EOF
exit 2