Безопасность, приватность и устойчивость
English version: 04-security-resilience.md. Этот файл — русский дубликат; обновляется вместе с 04-security-resilience.md.
Что хранит Binnacle, кто может достучаться до его демона, где лежат его секреты и что продолжает работать, когда какой-то части нет. Как сообщить об уязвимости — в политике безопасности.
Что хранит telemetry
Telemetry — это только метаданные. Хранилище держит для каждого вызова или события:
- harness, сессию и её субагентов, проект, рабочий каталог и ветку;
- временные метки, provider и модель;
- счётчики токенов и cache, с их происхождением, и
null, где harness их не сообщает; - compaction, упоры в лимиты использования и собственные события демона.
Оно никогда не хранит промпты, ответы модели, содержимое исходных файлов, секреты или аргументы инструментов. В экспорте OpenTelemetry, который настраивает binn init, логирование промптов выключено. Диагностика на уровне содержимого, если её когда-нибудь добавят, должна включаться только явно.
Секреты
- Никаких API-ключей в
.binnacle/project.yaml: Binnacle никогда не читает секрет из манифеста и не пишет его туда. - Ключи живут в окружении, в хранилище секретов операционной системы или в собственной конфигурации upstream-клиента.
- Никогда намеренно не экспортируйте секрет в Obsidian или Graphify.
binn auditпока не ищет закоммиченные секреты. Это добавляет фаза 12 вdocs/05-mvp-plan.md: закоммиченный.envи известные шаблоны ключей, с путём и строкой, но никогда со значением.
Учётные данные tracker
Binnacle никогда не пишет в tracker (ADR-0013), поэтому просит токены только на чтение: утёкший токен не может изменить репозиторий.
| Tracker | Токен | Его доступ |
|---|---|---|
| GitHub | fine-grained | чтение Issues; для CI в snapshot — чтение Actions, Commit statuses и Pull requests |
| GitLab | любой | read_api |
- Токен задаётся в окружении демона как
BINNACLE_GITHUB_TOKENилиBINNACLE_GITLAB_TOKENлибо в~/.binnacle/credentials.json, по одному на хост. Демон, запущенный автозапуском, таких переменных не получает, поэтому храните его токены в файле. Как — в чек-листе установки. - Файл учётных данных, который могут читать другие, отвергается с
tracker.credentials_insecure. - Токен отправляется только на свой объявленный хост и никогда не появляется в ответе, диагностике, событии или строке лога.
- GitHub отдаёт check runs только GitHub Apps, поэтому Binnacle читает workflow runs и statuses коммита и никогда — его содержимое.
- Токены никогда не импортируются из
ghилиglab: их токены обычно могут писать, и обещание выше было бы нарушено.
CI, прочитанный из Git remote, а не из tracker, идёт на хост, который не объявлял ни один манифест. На github.com или gitlab.com используется токен, хранимый для этого хоста. На любом другом хосте — только запись файла учётных данных для него и никогда токен из окружения, чтобы remote не мог вытянуть токен, предназначенный для другого хоста.
Локальная сеть
Демон слушает только 127.0.0.1, если BINNACLE_HOST не задаёт 0.0.0.0, как в контейнере. Loopback — не граница аутентификации: до него может достучаться любая вкладка браузера пользователя. Учётных записей нет, потому что пользователь один; вместо них демон охраняют токен и две проверки заголовков.
| Путь | Токен | Что делает |
|---|---|---|
GET /health | нет | Говорит, слушает ли демон Binnacle и какой он версии; больше ничего |
POST /v1/logs | нет | Принимает логи OpenTelemetry: экспортёр harness настраивается эндпоинтом и ничем больше. Сохраняет метаданные каждого вызова и счётчики токенов и ни на какой вопрос не отвечает. Принимает вызовы только с loopback этой машины, на каком бы адресе ни слушал демон |
POST /v1/metrics, POST /v1/traces | нет | Отвечает, но не хранит |
POST /ops/<operation> | bearer | Каждая операция: CLI, binn mcp и dashboard |
любой другой GET | нет | Сгенерированные файлы dashboard, в которых нет данных проекта |
Каждый путь, в том числе без токена, проверяется дважды:
Hostдолжен быть ровно собственным адресом демона,127.0.0.1:<port>, или значениемhost:portизBINNACLE_ALLOWED_HOSTS: неlocalhost:<port>и не другим именем, если его нет в списке.Origin, если он отправлен, должен бытьhttp://с одним из этих адресов.
Вместе они отражают DNS rebinding. Кроме того, страницы dashboard несут Content-Security-Policy: они ничего не загружают и ни с чем не соединяются, кроме демона, и запускают только те inline-скрипты, что есть в отданном HTML.
binn mcp говорит с harness по MCP через stdio и вызывает демон с токеном, как любой другой клиент.
Токен dashboard
binn dashboardоткрывает dashboard с токеном во фрагменте адреса, который никогда не доходит до сервера. Страница переносит его в local storage браузера (ADR-0031).binn dashboardпечатает адрес без токена, потому что вывод shell у навыка доходит до provider модели.binn dashboard --print, для человека у терминала, печатает адрес с токеном.
Удалённый или командный доступ — это post-MVP, и для него нужны собственные аутентификация и модель угроз.
Права на файлы
Всё, что Binnacle хранит о себе, лежит в домашнем каталоге Binnacle: по умолчанию ~/.binnacle или каталог, который называет BINNACLE_HOME. Каталог создаётся с 0700, а файлы, которые Binnacle там пишет, получают 0600:
- токен API;
- runtime-файл демона и его лог;
- хранилище, чьи служебные файлы SQLite защищает
0700каталога; - реестр проектов;
- файл настроек.
0600 и 0700 — режимы POSIX. В Windows они не применяются: Node передаёт режим, а файловая система его игнорирует.
- Там эти файлы защищены ACL профиля пользователя и ничем из того, что делает Binnacle.
- Всё, что запущено под этой учётной записью Windows, может прочитать токен API.
- Это та же граница, за которой уже лежат собственные файлы учётных данных harness, но это не защита, которую даёт Binnacle, и эта страница не делает вид, что она есть.
Открытые advisories зависимостей
pnpm audit --prod не сообщает ни одного advisory уровня high или critical. pnpm audit всё ещё сообщает перечисленные ниже, все — в инструментах сборки dashboard. Они работают при nuxt generate и никогда не поставляются: dashboard отдаётся как статические файлы (ADR-0031). Каждый оставлен, потому что ни один релиз прямой зависимости его не убирает (2026-10-13).
| Advisory | Пакет, через | Серьёзность | Почему оставлен | Вернуться, когда |
|---|---|---|---|---|
| GHSA-x6jw-m9v5-85vh, GHSA-v5rq-49vh-5v5c, GHSA-g4wm-2vf7-vfgr, GHSA-858h-whjf-mvg5 | simple-git 3.x и @simple-git/argv-parser, через nuxt → @nuxt/devtools 3 | critical, high | Исправлено в simple-git 4, который не берёт ни один @nuxt/devtools 3; его убирает только devtools 4, всё ещё beta, а Nuxt 4.6 требует devtools 3. Dashboard выключает devtools, и они работают только под nuxt dev. | стабильный Nuxt возьмёт @nuxt/devtools 4 |
| GHSA-86w9-cpqp-85rv | node-forge, через nitropack → listhen | high | Исправленного релиза нет. listhen — слушатель сервера разработки; nuxt generate не проверяет им ни одной подписи. | node-forge выпустит исправление |
| GHSA-vfj7-8cjw-p6xm | braces, через nitropack → globby → micromatch | high | Исправленного релиза нет. Шаблоны, которые он раскрывает, — собственные шаблоны dashboard во время сборки, так что худший случай — неудачная сборка. | braces выпустит исправление |
| GHSA-g7r4-m6w7-qqqr | esbuild 0.27, через @nuxt/ui → @nuxt/fonts 0.14 → fontless | low | Последний Nuxt UI всё ещё берёт @nuxt/fonts 0.14. Уязвимость касается сервера разработки esbuild в Windows, который dashboard никогда не запускает, а шрифты Nuxt UI dashboard выключает. | Nuxt UI возьмёт @nuxt/fonts 1 |
Восстановимость
Локальное хранилище SQLite — пересобираемая проекция, а не источник истины: знание о проекте остаётся в Git, tracker и документах. Потеря хранилища может стоить истории telemetry, но никогда — решения.
Плавная деградация
Когда опциональной части нет, работа продолжается:
| Нет | Что происходит |
|---|---|
| Graphify | Агенты используют Serena, исходники и документы |
| Obsidian | Канонические документы не затронуты |
| Binnacle | Обычный workflow агентов и Git продолжается |
| Адаптера telemetry | Работа продолжается; метрики за этот интервал неполны и так и помечены |