diff --git a/README.md b/README.md index 2bc3115..0a33228 100644 --- a/README.md +++ b/README.md @@ -340,66 +340,86 @@ dsh-memory/ | _mcp_tools | Список MCP-инструментов ArtCraft-приложения (params: filter, brief) | нет | | _mcp_call | Вызов MCP-инструмента ArtCraft-приложения (params: tool, arguments) | нет | -### Что разрешено в dsh_bash без подтверждения +### Safe-list: что выполняется без подтверждения -Базовые команды: -pwd, dir, ls, tree, type, where, whoami +Кроссплатформенный список (Windows + Unix). Только команды, которые не читают содержимое файлов. -Git только на чтение: -git status, git diff, git log, git show, git branch, git rev-parse, git ls-files, git describe, git remote +**Базовые:** `pwd`, `dir`, `ls`, `tree`, `where`, `which`, `whoami`, `hostname`, `uname`, `ver`, `cd`, `echo`, `date`, `time`. -Менеджеры пакетов (подкоманды): -npm, pnpm, yarn, bun — только test, run, build, lint, typecheck, check, --version, ls, list, why, outdated +**Git только на чтение:** `status`, `diff`, `log`, `show`, `branch`, `rev-parse`, `ls-files`, `describe`, `remote`, `config`. Глобальные флаги перед подкомандой пропускаются: `git -C status`, `git -c key=val log`, `git --no-pager log` — всё это safe-list. -Утилиты через npx: -tsc, eslint, prettier, vitest, jest, mocha +**Менеджеры пакетов:** `npm`, `pnpm`, `yarn`, `bun` — подкоманды `test`, `run`, `build`, `lint`, `typecheck`, `check`, `--version`, `ls`, `list`, `why`, `outdated`, `info`, `view`. Глобальные `--prefix`, `--workspace`, `-w` пропускаются. -Напрямую: tsc, eslint +**Через npx:** `tsc`, `eslint`, `prettier`, `vitest`, `jest`, `mocha`. -Версии: node --version, npm --version, npx --version +**Напрямую:** `tsc`, `eslint`, `node --version`, `npm --version`, `npx --version`. -### Что заблокировано всегда +**Не включены сознательно:** `cat`, `head`, `tail`, `type`, `more`, `less`. Они читают файлы в обход `validatePath`, включая `.env` и ключи. Поэтому идут в confirm. -Удаление и перемещение: -rm, del, rd, rmdir, mv, move, cp, copy, dd +**Любой policy-флаг отменяет allow.** Даже safe-команда с `|`, `&&`, `;`, `$`, абсолютным путём или `..` уходит в confirm. -Системные команды: -shutdown, taskkill, tskill, reg, netsh, setx, sudo, sc, schtasks, format X: +### Policy-флаги -Сеть и загрузка: -curl, wget, ssh, scp, sftp, ftp, certutil, bitsadmin, mshta, rundll32, regsvr32 +| Флаг | Что означает | +|---|---| +| `shell` | символы `|` `&` `>` `<` `;` обратный апостроф `$` | +| `multiline` | перенос строки | +| `destructive` | `rm`, `del`, `format`, `mv`, `cp`, `git push/commit/reset/clean`, `taskkill`, `reg`, `sc`, `schtasks` | +| `network` | `curl`, `wget`, `ssh`, `scp`, `ftp`, `powershell`, `iwr` | +| `absolute-path` | `C:/...`, `//...`, `/path` | +| `parent-path` | `..` | +| не в safe-list | всё остальное, например `node script.mjs` | + +Флаги пишутся в ответ (`policyFlags`) и в консоль моста: `[bash] policy flags: destructive,shell :: rm -rf tmp`. -PowerShell: -powershell, pwsh, iwr, irm, invoke-expression, invoke-webrequest +### Что требует подтверждения в панели -Git на запись: -git push, commit, checkout, switch, reset, clean, rebase, merge, stash, restore, rm, mv, apply, cherry-pick, revert, tag, am, filter-branch, bisect +Всё, что не в safe-list или имеет policy-флаг: `rm -rf tmp`, `curl http://x`, `git push`, `node script.mjs`, `cat .env`, `ls ..`, `pwd && dir`. -Управление сетью Windows: -net use, net user, net localgroup, net share, net stop, net start, net session, net file, net time, net accounts +При вызове в панели появляется попап **Allow / Deny**. Модель ждёт: -Метасимволы в командах: -вертикальная черта, амперсанд, угловые скобки, точка с запятой, обратный апостроф, знак доллара, переносы строк +- **Allow** — команда выполняется, результат возвращается. +- **Deny** — возвращается `E_USER_DENIED`, команда не выполняется, очередь идёт дальше. +- **Ничего не нажать** — очередь стоит. Сброс: Stop, затем Start. -### Что требует подтверждения в панели +Если панель недоступна, confirm закрывается в отказ: `E_CONFIRM_UNAVAILABLE`. Это fail-closed: без явного «да» команда не выполняется. + +### Что блокируется жёстко + +Только два случая: пустая команда и команда длиннее 2000 символов. Всё остальное, включая `rm`, `curl`, `powershell`, `git push`, выполнимо через подтверждение. + +### Pre-flight политика (главный слой) -Команда не в whitelist, но и не в blacklist. Например: `node script.mjs`, `python main.py`, `go build`, `cargo test`. +Модель обязана объявлять до отправки. Это записано в протоколе памяти (`protocol_policy`). Перед `dsh_bash` с policy-флагом модель пишет в тексте: -При такой команде в панели появляется попап с двумя кнопками Allow и Deny. Модель ждёт. Нажмите Allow — команда выполнится. Deny — вернётся ошибка E_USER_DENIED. +``` +Policy: destructive, shell +Собираюсь выполнить (нужно ваше да): + 1. rm -rf V:/Site/tmp/build +Не отправляю вызовы, жду подтверждения. +``` + +и останавливается. Пользователь отвечает «да» или «нет» в чате. Это настоящий контроль: команды видны целиком до выполнения. Панельный confirm — страховка, если модель забыла объявить. + +### Чем это отличается от прежней блокировки + +Раньше метасимволы и blacklist-паттерны блокировали команду намертво. Это создавало видимость защиты: обход через `node script.mjs` или `node -e` был тривиален и не логировался. Сейчас программа не блокирует, а спрашивает; каждое срабатывание флага пишется в консоль моста; граница — клик Allow/Deny и pre-flight объявление модели. + +Ограничение, которое надо понимать: модель не детерминирована, она может забыть объявить. Тогда сработает панельный confirm, и вы увидите факт нарушения протокола. Если она забыла объявить, а вы нажали Allow не глядя, команда выполнится. Это осознанный выбор в пользу «человек решает», а не «программа запрещает». ### Защита от чтения секретов Прочитать нельзя (E_FORBIDDEN_PATH): -- .pem, .key, id_rsa, id_ed25519, .pfx, .p12 -- файлы с именем credential или secrets в имени (.json, .yaml, .txt) +- `.pem`, `.key`, `id_rsa`, `id_ed25519`, `.pfx`, `.p12` +- файлы с `credential` или `secrets` в имени (`.json`, `.yaml`, `.txt`) -Запись в .env, package.json, package-lock.json, pnpm-lock.yaml, yarn.lock требует подтверждения в панели. +Запись в `.env`, `package.json`, `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock` требует подтверждения в панели. ### Защита путей -Все пути относительные от папки из allowedRoots. Абсолютные пути запрещены. Попытка выйти за пределы через `..` или символическую ссылку даёт E_PATH_ESCAPE. +Для `dsh_read`, `dsh_write`, `dsh_edit`, `dsh_search`, `dsh_tree`: все пути относительные от `allowedRoots`, абсолютные запрещены, выход через `..` или символическую ссылку даёт `E_PATH_ESCAPE`. ---- +Важно: это не распространяется на `dsh_bash` и запускаемые скрипты (`node`, `python`). Команда в shell работает под правами пользователя и может читать и писать за пределами workspace. Единственная защита здесь — policy-флаги (`absolute-path`, `parent-path`) плюс подтверждение. Именно поэтому `cat`, `type`, `head`, `tail` убраны из safe-list. ## Интерфейс панели