chore(permissions): expand global allow-list with read-only commands #35
Loading…
Reference in a new issue
No description provided.
Delete branch "chore/permissions/expand-allow-list"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Что сделано
Bucket A — глобальный allow-list (
.opencode/opencode.json, блокpermission.bash)Read-only утилиты (24 паттерна):
echo *,test -f *,test -d *,pwd,pwd *,date,date *,which *,bash -n *wc*,wc *,grep *,rg *,find *,ls *head*,tail*,head *,tail *,sed -n *,od *,xxd *,xxdRead-only git subcommands (9 паттернов):
git rev-parse *,git remote -v*,git remote show*,git remote get-url *git show*,git fetch*,git blame*,git ls-tree*,git ls-files*Read-only
git -C *subcommands (8 паттернов):git -C * show*,git -C * blame*,git -C * fetch*,git -C * remote -v*git -C * remote show*,git -C * ls-tree*,git -C * ls-files*,git -C * rev-parse *Read-only registry/version queries (5 паттернов):
node --version*,node -v*,npm view *,npm ls *,npm audit*cat *(1 паттерн) — добавлен ПЕРВЫМ в блокеpermission.bash, ДО deny-правил секретов.Bucket B — per-agent allow-list (
.opencode/agents/reviewer.md, блокpermission.bash)ruff check*,ruff format --check*,gh auth status*— узкие read-only правила, рядом сuv run */pytest*.4 логических коммита
add read-only utils to global allow-list— 24 утилитыadd read-only git subcommands to global allow-list— 9 git + 8git -C *add cat to global allow-list with deny-ordering invariant—cat *(findLast guard)add registry queries and per-agent reviewer rules— 5 registry + 3 reviewerПочему
Агенты
generalиexploreне имеют per-agentpermission.bashи работают только на глобальном allow-list. Глобальный список содержит git/docker/uv/npm/python/ssh паттерны, но НЕ содержит базовых read-only утилит inspection (echo,cat,head,tail,rg,grep,find,ls,wc,pwd,which,date,test,sed -n,od,xxd) и read-only git subcommands (git rev-parse,git remote -v/show/get-url,git show,git fetch,git blame,git ls-tree,git ls-files). Каждый такой вызов попадал в catch-all → ask → подтверждение пользователем.Исторический анализ логов (187k строк, 2026-06-10 → 2026-07-20) зафиксировал ~128 ask-событий, большинство — routine read-only команды. Цель — промотировать безопасные read-only команды в глобальный allow-list для снижения prompt fatigue, сохранив gating деструктивных команд.
Bucket B добавлен per-agent (НЕ глобально): bare
ruff format(без--check) переписывает файлы — только read-only формы безопасны;gh *глобально = slippery slope кgh pr merge(MUST stay gated).Watch out
cat *: allowпомещён ДО deny-правил секретов (cat .env*,*cat */.env*,cat *id_ed25519*,*cat *ssh/id_ed25519*). opencode permission matching используетfindLast(последнее совпадающее правило побеждает). Еслиcat *: allowстоит ПОСЛЕcat .env*: deny, allow переопределит deny → секреты утекут. Порядок верифицирован:cat *на позиции 0,cat .env*на позиции 1,cat *id_ed25519*и*cat *ssh/id_ed25519*также после. См.## Инвариантыв issue.&&-chaining caveat: opencode матчит ВСЮ строку команды как один unit.echo "---" && git statusНЕ матчит ниecho *, ниgit status*→ catch-all → ask. Это ограничение opencode (memorytechnical/opencode-permission-ampersand-blocking.md), НЕ лечится allow-list. Mitigation: дисциплина в промптах агентов (не чейнить). Bucket A устраняет single-command asks (большинство), но chained команды всё равно ask.gh pr mergeоставлен gated (нет правила ни глобально, ни per-agent) — reviewer protocol violation guardrail (13 исторических попыток). НЕ добавлять.python3 *НЕ добавлен вmemory-syncer.md— bypass risk черезsubprocess.run(обходит bash permission).git clone*— уже deny, НЕ менялся.Pending
cat .envordering верифицирован вручную через JSON inspection (позицияcat *: 0<cat .env*: 1<cat *id_ed25519*: 122<*cat *ssh/id_ed25519*: 123). findLast semantics корректны: дляcat .envпобеждаетdeny. Автоматический тест ordering-инварианта — отдельная задача (вне scope issue #34).&&-chaining mitigation требует промпт-дисциплины агентов (не лечится конфигом).Closes #34
Closes #34
Code Review Summary
PR расширяет глобальный allow-list в
.opencode/opencode.json(46 паттернов) и per-agent allow-list в.opencode/agents/reviewer.md(3 паттерна) read-only командами. Конфигурационный PR, не код — проверен на JSON-валидность, security ordering invariant, отсутствие деструктивных команд, scope (memory-syncer не тронут).Positives
cat *: allowстоит на позиции 0, ДО всех deny-правил секретов:cat .env*(pos 1),*cat */.env*(pos 2),cat *id_ed25519*(pos 122),*cat *ssh/id_ed25519*(pos 123). findLast semantics: дляcat .envпобеждаетdeny(последнее совпадение). Секреты НЕ утекут. Это критический security-чек — пройден.python3 -c "import json; json.load(...)"→ OK. Нет синтаксических ошибок, запятые/кавычки корректны.echo *,test -f/-d *,pwd,date,which *,bash -n *,wc*,grep *,rg *,find *,ls *,head*,tail*,sed -n *,od *,xxd *, read-only git subcommands (rev-parse,remote -v/show/get-url,show,fetch,blame,ls-tree,ls-files) +git -C *аналоги, registry queries (node --version,npm view,npm ls,npm audit). Ни одной деструктивной команды.gh pr merge,git reset,git rm,git push --force,git commit, bareruff format(мутирующий),python3 *в memory-syncer,git clone— отсутствуют в diff.git clone*остался deny..opencode/opencode.jsonи.opencode/agents/reviewer.md. Bypass risk черезpython3 *в memory-syncer отсутствует.ruff check*,ruff format --check*(с--check— не мутирует),gh auth status*. Bareruff format(без--check) НЕ добавлен — корректно, т.к. он переписывает файлы.## Что сделано,## Почему,## Watch out,## Pending) заполнены осмысленно,Closes #34присутствует. Watch out детально описывает findLast invariant и&&-chaining caveat..opencode/opencode.json(project-local, auto-discovered), НЕ в~/.config/opencode/. Соответствует skillconfigure-opencode(canonical rule).Suggestions (info, not blocking)
npm audit*также матчитnpm audit fixиnpm audit fix --force, которые мутируютpackage.json/package-lock.json. Если хочется строго read-only — сузить доnpm audit(без wildcard) илиnpm audit --json*. Не критично:npm audit fixне вызывает потерю данных или утечку секретов, но нарушает декларированный в PR body «read-only registry queries» принцип.find *матчитfind . -deleteиfind . -exec rm {} \;(деструктивные формы).findбез флагов read-only, но wildcard допускает-delete/-exec. Сузить доfind * -type *или явных read-only форм сложно (glob не expressive enough). Mitigation: дисциплина в промптах агентов. Не блокирующее —find -deleteредко используется агентами в routine inspection.sed -n *—sed -nsuppresses auto-print, ноsed -n '1d;p'всё равно может выполнять команды в потоке (не в файле без-i). Паттерн НЕ матчитsed -i(требует-nв начале) — корректно, read-only. ОК, просто отмечено для полноты анализа.Verdict: APPROVE