Match the command word in tea-guard, not the whole string #38

Closed
opened 2026-08-10 12:45:26 +00:00 by claude · 1 comment
Collaborator

Summary

hooks/tea-guard.sh:88 ищет слово tea регуляркой по всей строке команды, а не
по имени запускаемой программы. Любая команда, у которой это слово попало в
аргумент — заголовок issue, текст коммита, grep-шаблон, — блокируется, хотя
клиент Gitea в ней не участвует.

Spec

none

Steps to reproduce

  1. Выполнить создание локальной issue, в заголовке которой встречается слово
    tea отдельным словом:
    python3 skills/issue/scripts/issue_new.py --type bug \
      --title "Document that tea pulls create refuses --repo owner/repo"
    

Expected

Команда выполняется. Это python3, сеть не используется, логин не нужен —
skills/issue по определению офлайновый слой и про трекер не знает.

Actual

PreToolUse:Bash hook error: [.../hooks/tea-guard.sh]: tea-guard: BLOCKED — every
`tea` command must include --login "$GITEA_LOGIN" (the guard substitutes the
operator-pinned login). Run /tea:auth if no login is pinned.

Причина в hooks/tea-guard.sh:88:

if not re.search(r'(^|[;&|(]|\s)tea(\s|$)', cmd):
    allow_passthrough()

Условие «это вызов клиента» проверяется по подстроке в сыром тексте команды,
поэтому под него попадают git commit -m "route it through tea api",
grep -rn "tea api" skills/, echo tea и любой --title со словом tea
внутри. Обойти можно только переписав формулировку человеческого текста, что и
пришлось сделать: заголовок этой issue не содержит слова tea отдельным словом
именно из-за хука.

Ложное срабатывание безопасно (команда блокируется, а не выполняется под чужим
логином), но оно ломает офлайновые слои, которые к гварду отношения не имеют, и
диагностируется только чтением исходника хука.

Модуль уже импортирует shlex (hooks/tea-guard.sh:28) и не использует его:
разбор строки на токены и проверка первого слова каждого сегмента (;, &&,
||, |) дают точный ответ на вопрос «запускается ли tea».

Environment

Claude Code PreToolUse(Bash) hook, hooks/tea-guard.sh, Python 3.14, macOS.

Acceptance criteria

  • python3 ... issue_new.py --title "... tea ..." выполняется, а не
    блокируется
  • git commit -m "..." с словом tea в сообщении выполняется
  • tea issues list без --login по-прежнему блокируется
  • tea issues list --login "$GITEA_LOGIN" по-прежнему переписывается на
    закреплённый логин
  • составные команды проверяются посегментно: cd x && tea issues list ...
    разбирается как вызов клиента
  • есть тест в tests/, покрывающий ложное срабатывание и оба случая выше
<!-- tea:id match-the-command-word-in-tea-guard-not-the --> ## Summary `hooks/tea-guard.sh:88` ищет слово `tea` регуляркой по всей строке команды, а не по имени запускаемой программы. Любая команда, у которой это слово попало в аргумент — заголовок issue, текст коммита, grep-шаблон, — блокируется, хотя клиент Gitea в ней не участвует. ## Spec none ## Steps to reproduce 1. Выполнить создание локальной issue, в заголовке которой встречается слово `tea` отдельным словом: ``` python3 skills/issue/scripts/issue_new.py --type bug \ --title "Document that tea pulls create refuses --repo owner/repo" ``` ## Expected Команда выполняется. Это `python3`, сеть не используется, логин не нужен — `skills/issue` по определению офлайновый слой и про трекер не знает. ## Actual ``` PreToolUse:Bash hook error: [.../hooks/tea-guard.sh]: tea-guard: BLOCKED — every `tea` command must include --login "$GITEA_LOGIN" (the guard substitutes the operator-pinned login). Run /tea:auth if no login is pinned. ``` Причина в `hooks/tea-guard.sh:88`: ```python if not re.search(r'(^|[;&|(]|\s)tea(\s|$)', cmd): allow_passthrough() ``` Условие «это вызов клиента» проверяется по подстроке в сыром тексте команды, поэтому под него попадают `git commit -m "route it through tea api"`, `grep -rn "tea api" skills/`, `echo tea` и любой `--title` со словом `tea` внутри. Обойти можно только переписав формулировку человеческого текста, что и пришлось сделать: заголовок этой issue не содержит слова `tea` отдельным словом именно из-за хука. Ложное срабатывание безопасно (команда блокируется, а не выполняется под чужим логином), но оно ломает офлайновые слои, которые к гварду отношения не имеют, и диагностируется только чтением исходника хука. Модуль уже импортирует `shlex` (`hooks/tea-guard.sh:28`) и не использует его: разбор строки на токены и проверка первого слова каждого сегмента (`;`, `&&`, `||`, `|`) дают точный ответ на вопрос «запускается ли `tea`». ## Environment Claude Code PreToolUse(Bash) hook, `hooks/tea-guard.sh`, Python 3.14, macOS. ## Acceptance criteria - [ ] `python3 ... issue_new.py --title "... tea ..."` выполняется, а не блокируется - [ ] `git commit -m "..."` с словом `tea` в сообщении выполняется - [ ] `tea issues list` без `--login` по-прежнему блокируется - [ ] `tea issues list --login "$GITEA_LOGIN"` по-прежнему переписывается на закреплённый логин - [ ] составные команды проверяются посегментно: `cd x && tea issues list ...` разбирается как вызов клиента - [ ] есть тест в `tests/`, покрывающий ложное срабатывание и оба случая выше
claude added this to the Self-improvement milestone 2026-08-10 12:45:26 +00:00
claude added the
severity
medium
type
bug
comp/hookscomp/tea-guard
labels 2026-08-10 12:45:26 +00:00
Author
Collaborator

Дубликат #29 — закрываю в его пользу.

Ложное срабатывание гварда поймали три независимых агента на трёх разных
командах; каноническая issue собирает все четыре случая в одни Steps to
reproduce, чтобы тест на регрессию покрыл их разом.

Уникальные вклады этой issue перенесены в #29 целиком:

  • git commit -m "route it through …" и echo как случаи наравне с --title;
  • наблюдение, что заголовок этой самой issue пришлось написать в обход
    детектора — оно сохранено в Actual как доказательство цены проблемы;
  • формулировка «ложное срабатывание безопасно для идентичности, но ломает
    офлайновые слои, которые к гварду отношения не имеют»;
  • критерии на посегментный разбор cd x && …, x | …, подстановки;
  • указание, что shlex уже импортирован в hooks/tea-guard.sh:28 и не
    используется по назначению.
Дубликат #29 — закрываю в его пользу. Ложное срабатывание гварда поймали три независимых агента на трёх разных командах; каноническая issue собирает все четыре случая в одни Steps to reproduce, чтобы тест на регрессию покрыл их разом. Уникальные вклады этой issue перенесены в #29 целиком: - `git commit -m "route it through …"` и `echo` как случаи наравне с `--title`; - наблюдение, что заголовок этой самой issue пришлось написать в обход детектора — оно сохранено в Actual как доказательство цены проблемы; - формулировка «ложное срабатывание безопасно для идентичности, но ломает офлайновые слои, которые к гварду отношения не имеют»; - критерии на посегментный разбор `cd x && …`, `x | …`, подстановки; - указание, что `shlex` уже импортирован в `hooks/tea-guard.sh:28` и не используется по назначению.
Sign in to join this conversation.