From ad784125222d12c39ce5309b78d722f237a02d81 Mon Sep 17 00:00:00 2001 From: richblack Date: Tue, 21 Jul 2026 10:54:16 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20template=201.16.1=E2=80=94=E2=80=94wik?= =?UTF-8?q?i-first-search=20=E8=A3=9C=20Bash=20=E7=A0=B4=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.16.0 只掛 Grep|Glob|Read,但「用 curl/wrangler 亂試方法」走 Bash → hook 不觸發, 上線隔天即被繞過(leo 2026-07-21 實證:wiki 早記著寄信已驗證可用,我沒查又自創)。 matcher 補 Bash,只認高風險指令(wrangler|curl|npx|acr|gh|deploy|push)。 本 repo 亦需警覺:動外部系統前先看 hook 推的 wiki 命中,別自創方法。 Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/hooks/wiki-first-search.sh | 14 ++++++++++++++ .claude/settings.json | 2 +- system-dev/VERSION | 2 +- system-dev/scripts/update.sh | 7 ++++++- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/.claude/hooks/wiki-first-search.sh b/.claude/hooks/wiki-first-search.sh index 309d637..6d75785 100755 --- a/.claude/hooks/wiki-first-search.sh +++ b/.claude/hooks/wiki-first-search.sh @@ -29,6 +29,20 @@ try: if not q: p = ti.get('file_path') or ti.get('path') or '' q = os.path.splitext(os.path.basename(p))[0] if p else '' + if not q: + # Bash:2026-07-21 補的破口——原版只掛 Grep|Glob|Read, + # 但「用 curl/wrangler 亂試部署方法」走的是 Bash,整支 hook 不觸發。 + # leo 當場點破:wiki 早記著「寄信已驗證可用」,我卻沒查又自創方法。 + # 只認「會動到外部系統/部署」的高風險指令,避免每個 ls 都洗版。 + cmd = ti.get('command') or '' + if re.search(r'\b(wrangler|curl|npx|acr|gh|deploy|push)\b', cmd): + # 取指令中最具識別度的詞(worker 名/資源名/子命令)當搜尋詞 + cand = re.findall(r'[A-Za-z_][A-Za-z0-9_-]{4,}', cmd) + skip = {'https','http','client','accounts','workers','scripts', + 'application','content','Authorization','Bearer','python3', + 'curl','npx','bash','echo','grep','local','branch','origin'} + cand = [c for c in cand if c not in skip and not c.startswith('-')] + q = max(cand, key=len) if cand else '' # grep pattern 常含 regex 元字元;取最長的英數/底線詞當搜尋詞 words = re.findall(r'[A-Za-z_][A-Za-z0-9_]{3,}', q) print(max(words, key=len) if words else '') diff --git a/.claude/settings.json b/.claude/settings.json index 549e5ef..e7f76ab 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -27,7 +27,7 @@ ] }, { - "matcher": "Grep|Glob|Read", + "matcher": "Grep|Glob|Read|Bash", "hooks": [ { "type": "command", diff --git a/system-dev/VERSION b/system-dev/VERSION index 15b989e..41c11ff 100644 --- a/system-dev/VERSION +++ b/system-dev/VERSION @@ -1 +1 @@ -1.16.0 +1.16.1 diff --git a/system-dev/scripts/update.sh b/system-dev/scripts/update.sh index 823ab46..fe3d868 100755 --- a/system-dev/scripts/update.sh +++ b/system-dev/scripts/update.sh @@ -355,8 +355,13 @@ except Exception: pre = d.setdefault("hooks", {}).setdefault("PreToolUse", []) blob = json.dumps(pre) added = [] +# 1.16.1:既有註冊若漏 Bash(原版只掛 Grep|Glob|Read)就地補上—— +# 破口實例:用 curl/wrangler 亂試部署方法走 Bash,整支 hook 不觸發。 +for _e in pre: + if "wiki-first-search" in json.dumps(_e) and "Bash" not in _e.get("matcher", ""): + _e["matcher"] = "Grep|Glob|Read|Bash"; added.append("wiki-first-search(補Bash)") if "wiki-first-search" not in blob: - pre.append({"matcher": "Grep|Glob|Read", "hooks": [ + pre.append({"matcher": "Grep|Glob|Read|Bash", "hooks": [ {"type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/wiki-first-search.sh"}]}) added.append("wiki-first-search") if "subagent-wiki-guard" not in blob: