Когда вы указываете AI-ассистент кодирования на вашу инфраструктуру, CLI Rediacc обнаруживает это. Если Claude Code, Cursor, Gemini CLI, Copilot CLI или любой другой AI-ассистент кодирования управляет rdc, CLI применяет иной набор правил, чем для человека за клавиатурой. На этой странице объясняется, что агент может делать, что не может, и как защитные ограничения удерживаются даже тогда, когда агент пытается их обойти.
Краткий справочник: что агенты могут и не могут делать
| Операция | Поведение агента по умолчанию | Как разблокировать для конкретного случая |
|---|---|---|
rdc config show (с редактированием) | ✅ allowed | |
rdc config field get --pointer <pointer> (заглушка или дайджест) | ✅ allowed | |
rdc config field get --pointer <pointer> --digest | ✅ allowed | |
rdc config field set --pointer <pointer> (публичное поле) | ✅ allowed | |
rdc config field set --pointer <pointer> (чувствительное поле, с корректным --current) | ✅ allowed | |
rdc config edit --dump (редактированный JSONC) | ✅ allowed | |
rdc config audit {log, tail, verify} | ✅ allowed | |
rdc config field set --pointer <pointer> (чувствительное поле, без --current) | 🔴 refused | Указать --current "<старое значение>" |
rdc config field get --pointer <pointer> --reveal | 🔴 refused | Использовать --digest вместо этого |
rdc config show --reveal | 🔴 refused | Использовать простой rdc config show |
rdc config edit (интерактивный редактор) | 🔴 refused | Человек устанавливает REDIACC_ALLOW_CONFIG_EDIT=* перед запуском агента |
rdc config edit --apply <file> | 🔴 refused | То же переопределение |
rdc config field rotate --pointer <pointer> | 🔴 refused | То же переопределение; использует интерактивное подтверждение |
rdc term connect -m <machine> (прямой SSH на машину) | 🔴 refused | Сначала сделать форк репозитория и подключиться к форку |
Всё, в чём агенту отказывается, записывается в журнал аудита с outcome: refused и причиной.
Как агенты обнаруживаются
CLI считает процесс агентом, если выполняется хотя бы одно из условий:
- Одна из переменных
REDIACC_AGENT,CLAUDECODE,GEMINI_CLI,COPILOT_CLIустановлена в"1", илиCURSOR_TRACE_IDустановлена вообще. - На Linux: любой родительский процесс в цепочке предков имеет одну из этих переменных в своём окружении (через
/proc/<pid>/environ). Даже если агент удалит свои переменные с помощьюenv -iили скрипта-обёртки, родительская цепочка всё равно сообщит CLI, кто его запустил.
Обнаружение выполняется один раз на процесс и кэшируется. Его нельзя отключить.
Модель шлюза знаний
Чувствительные изменения следуют соглашению passwd(1): чтобы изменить секрет, докажите, что вы его уже знали. Одинаково для людей и агентов. Оба проходят через один и тот же шлюз. Нет никакого обхода типа «я сижу за клавиатурой».
- Хотите ротировать токен API, хранящийся в
/credentials/cfDnsApiToken? - CLI спрашивает: «какое текущее значение?»
- Агент (или человек) предоставляет открытый текст через
--current "$OLD". CLI хэширует$OLDс помощью SHA-256 и сравнивает с дайджестом хранящегося значения. Совпадение → запись выполняется. Несоответствие → отклонено, зафиксировано в аудите. - Для ротации без проверки предыдущего значения передайте
--rotate-secret(взаимно исключающий с--current). Это громко записывается в журнал аудита как ротация.
Модель закрывает три поверхности атаки:
- Скрытая ротация: вызывающий (агент или человек) без предварительного доступа к
$OLDне может заменить его своим значением. - Утечка через зондирование: ответ с дайджестом никогда не содержит открытый текст; даже скомпрометированный журнал аудита показывает
expected abc12345…, got deadbeef…, не базовые значения. - Случайная перезапись конфигурации пользователя: требует намеренного
--currentкаждый раз, даже в TTY. Ловит ошибку «я хотел установить STRIPE_TEST, но я в shell’е prod».
Структурированные подсказки следующего действия
Когда предусловие не выполняется, JSON-конверт (--output json) содержит структурированное поле errors[].next, которое точно говорит агентам, что предложить человеку:
{
"errors": [{
"code": "PRECONDITION_MISMATCH",
"message": "...",
"next": {
"summary": "Provide the current value or acknowledge rotation.",
"options": [
{ "description": "Re-read current digest, then retry with --current",
"run": "rdc repo secret get --name mail --key STRIPE_KEY" },
{ "description": "Skip the precondition (rotation, audited)",
"run": "rdc repo secret set --name mail --key STRIPE_KEY --value <new> --mode file --rotate-secret" }
]
}
}]
}
Агенты должны передавать next.options[].run в неизменном виде человеку, вместо того, чтобы синтезировать свои команды. Это избегает режима «агент придумывает команду, которой не существует» и держит оператора в контроле над действием.
Практический пример
# Получить короткий дайджест заглушки редактирования (безопасно для агентов).
$ rdc config field get --pointer /credentials/cfDnsApiToken
{"pointer": "/credentials/cfDnsApiToken", "value": "<redacted:secret>:abc12345"}
# Попытка перезаписи без доказательства: отклонено.
$ rdc config field set --pointer /credentials/cfDnsApiToken --new '"agent-picked-value"'
✗ Precondition failed: sensitive path requires --current (or --rotate-secret)
# Предоставить текущий открытый текст: разрешено.
$ rdc config field set --pointer /credentials/cfDnsApiToken \
--current "$OLD_CF_TOKEN" \
--new "$NEW_CF_TOKEN"
Set /credentials/cfDnsApiToken
Если у агента никогда не было $OLD_CF_TOKEN, он не может выполнить предусловие, и ротация отклоняется. Пользователь, у которого есть токен, по-прежнему может это сделать через редактор или передав --current из своей оболочки.
Редактирование по умолчанию
Каждая команда rdc, которая читает чувствительное состояние: config show, config field get, config machine list, config edit --dump: возвращает заглушки редактирования для секретных полей, не открытый текст:
"sshKey": "<redacted:credential>:9f3a2c1b"
"cfDnsApiToken":"<redacted:secret>:abc12345"
"storages.s3-prod.vaultContent": "<redacted:secret>:1f2e3d4c"
8-символьный шестнадцатеричный суффикс заглушки: это первые 8 символов sha256(canonicalize(value)): достаточно для различения двух разных значений с первого взгляда, недостаточно для обратного вычисления. Агент может использовать заглушку для отслеживания изменения значения, не видя его никогда.
--reveal снимает редактирование для людей на интерактивном TTY. Агентам отказывается независимо от состояния TTY. Каждое разрешение записывает запись аудита reveal_granted; каждый отказ записывает запись refused с прикреплёнными сигналами агента актора.
Переопределение REDIACC_ALLOW_CONFIG_EDIT
Некоторые операции: интерактивный редактор, --apply, field rotate: существуют для людей и не имеют безопасного пути для агентов. Если вы активно хотите, чтобы агент выполнил одну из них, вы устанавливаете:
export REDIACC_ALLOW_CONFIG_EDIT='*' # полный обход
# или
export REDIACC_ALLOW_CONFIG_EDIT='/credentials/ssh/privateKey,/infra/cfDnsZoneId'
# (глобы области через запятую: подстановочные символы * допустимы на сегмент)
…и агент это наследует.
Важная деталь: переопределение должно появляться в процессе выше агента в цепочке предков. Если агент установит его в своём собственном окружении (или в порождённой им подоболочке), CLI откажет и сообщит об этом:
Interactive editor is blocked in agent environments (REDIACC_ALLOW_CONFIG_EDIT was set but ancestry verification failed: the override must be set by your shell, not by an agent).
Эффект: агент не может обойти ограничение, запустив export REDIACC_ALLOW_CONFIG_EDIT='*' в середине сессии. Только родительский процесс (вы, в своём терминале, перед запуском агента) может открыть эту дверь.
Поддержка платформ: как переопределение проверяется на каждой ОС
REDIACC_ALLOW_CONFIG_EDIT и REDIACC_ALLOW_GRAND_REPO оба полагаются на проверку цепочки предков, чтобы доказать, что переопределение установлено вами, а не внедрено агентом. Проверка работает на Linux, macOS и Windows, но источник данных, на который она опирается, отличается для каждой платформы, и уровень гарантии тоже различается:
| Платформа | Источник данных | Уровень гарантии |
|---|---|---|
| Linux | /proc/<pid>/environ для каждого процесса вверх по цепочке | Снимок в момент exec, предоставляемый ядром. Процесс не может ретроактивно отредактировать, с чем он был запущен. |
| macOS | Системный вызов kern.procargs2, читаемый небольшим вспомогательным инструментом внутри rdc | То же свойство снимка exec как на Linux. Читаемо для собственных процессов без прав администратора. |
| Windows | Блок живого окружения каждого родительского процесса (PEB), читаемый тем же вспомогательным инструментом с защитой от переиспользования PID | Слабее: Windows не хранит снимок exec, поэтому проверка читает текущую память. Родителям по-прежнему невозможно переписать себя чем-либо, что обычно запускает агент, но источник данных не заморожен ядром, как на Linux и macOS. |
На macOS и Windows CLI запускает свой встроенный бинарный файл renet для выполнения чтения; вспомогательный инструмент сообщает, какие из отслеживаемых переменных несёт каждый родитель, и вся логика решений остаётся в CLI. Если вспомогательный инструмент отсутствует, устарел или по какой-либо причине не работает, CLI не может проверить переопределение и отказывает безопасно: переопределение отклоняется и ошибка говорит, что проверка была недоступна, а не что вы что-то сделали неправильно. Рабочая установка никогда не покажет это сообщение; переустановка rdc восстанавливает вспомогательный инструмент.
Что остаётся верным на каждой платформе: переопределение должно быть уже присутствовать в окружении процесса агента при его запуске. Экспортируйте его в своём терминале, потом запустите агента. Агент, который устанавливает переменную в середине сессии, отклоняется.
Журнал аудита
Каждое изменение, каждый отказ, каждое разрешение --reveal записывает строку JSONL в ~/.config/rediacc/audit.log.jsonl (режим 0600, ротация при 10 МБ). Каждая строка связана хэшем: поле prevHash равно sha256("<предыдущая строка>"). Изменение любой строки разрывает цепочку во всех последующих строках.
{"ts":"2026-04-21T10:02:47.831Z","actor":{"kind":"agent","agentSignals":["CLAUDECODE"]},"command":"config field set","paths":["/credentials/cfDnsApiToken"],"outcome":"ok","configId":"...","configVersion":48,"prevHash":"sha256:9f3a..."}
{"ts":"2026-04-21T10:02:51.114Z","actor":{"kind":"agent","agentSignals":["CLAUDECODE"]},"command":"config edit","paths":[],"outcome":"refused","reason":"agent without REDIACC_ALLOW_CONFIG_EDIT=*","prevHash":"sha256:abc1..."}
{"ts":"2026-04-21T10:03:05.220Z","actor":{"kind":"human"},"command":"config show --reveal","paths":[],"outcome":"reveal_granted","configId":"...","configVersion":48,"prevHash":"sha256:deac..."}
Просмотр
# Список последних записей
rdc config audit log --since 24h
# Фильтр по глобу указателя
rdc config audit log --path '/credentials/*'
# Только записи от агентов
rdc config audit log --actor agent
# Потоковая трансляция новых записей в реальном времени (Ctrl+C для остановки)
rdc config audit tail
# Проверка целостности хэш-цепочки
rdc config audit verify
# → "Chain integrity verified across 247 entries."
# ИЛИ
# → "Chain broken at line 103: file has been tampered with or corrupted."
Что никогда не появляется в журнале аудита
- Открытый текст секретных значений
- Парольные фразы, токены, SSH-ключи
- Старые/новые значения при несоответствии предусловия
--current(только 8-символьный префикс дайджеста)
Журнал можно безопасно передать проверяющему безопасности или прикрепить к отчёту об ошибке.
Ограничения поведенческой модели
Ограничения агента являются поведенческими, а не криптографическими. Решительный или специально настроенный агент, работающий с тем же UID, что и файл конфигурации, всегда может выполнить cat ~/.config/rediacc/rediacc.json и прочитать открытый текст, поскольку файл доступен для чтения процессом.
Для настоящего криптографического контроля используйте зашифрованное хранилище конфигурации: секреты хранятся на стороне сервера, каждое чувствительное поле несёт HMAC-обязательство на уровне поля, и воркер аккаунта отклоняет записи, чьё предусловие --current не совпадает по хэшу с хранящимися данными. Сервер никогда не видит открытый текст (нулевое знание), но шлюз применяется принудительно.
Локальный файл: лёгкий путь безопасен. Удалённое хранилище: обходной путь криптографически труден.
Что Rediacc не изолирует
Защитные ограничения агента на этой странице защищают собственную инфраструктуру Rediacc: файл конфигурации, Docker-демон каждого репозитория, LUKS-зашифрованные данные репозитория, ограниченную SSH-песочницу. Они не защищают внешние сервисы, для которых ваш репозиторий хранит учётные данные.
Форк репозитория это BTRFS reflink тома родителя. Всё, что хранится на диске у родителя, побайтово идентично в форке: код, данные и .env файлы одинаково. Если ваш репозиторий содержит STRIPE_LIVE_KEY, AWS_ACCESS_KEY_ID, токен Railway API или любые другие долгоживущие учётные данные для стороннего сервиса, форк наследует их. Агент, работающий в песочнице форка, может прочитать этот файл, экспортировать значение или использовать его для вызовов стороннего API. У стороннего сервиса нет способа узнать, что вызов пришёл из форка, а не из продакшн.
Это линия разделения ответственности:
| Граница | Владелец |
|---|---|
| Данные репозитория, пространство имён монтирования, область Docker, защитные ограничения агента, журнал аудита, инъекция секрета во время развертывания | Rediacc |
| Код приложения, который использует эти секреты, и любые учётные данные, встроенные в образ во время сборки | Разработчик репозитория |
Основная защита встроена: секреты для каждого репозитория хранятся в отдельной области от зашифрованного образа репозитория и не копируются через границу форка. Контейнеры форка загружаются с пустой картой секретов и идентифицируют себя как другой внешний субъект, чем родитель. Устанавливайте их с помощью rdc repo secret set (режим env для интерполяции compose, режим file для блоков tmpfs secrets:). Шлюз мутации одинаков. И люди, и агенты должны предоставить --current (предусловие passwd-стиля) или --rotate-secret (ротация в журнале аудита) для перезаписи или удаления существующего значения.
Кроссрепозиторная изоляция применяется принудительно. Вредоносный или халатный compose-файл в репо B не может ссылаться на каталог секретов репо A. Валидатор compose renet жёстко отклоняет любой путь secrets: file:, configs: file: или env_file:, который указывает за пределы директории ${REDIACC_NETWORK_ID} текущего репо, и отклонение НЕ переопределяется с помощью --unsafe. Оборона в глубину: песочница Landlock вокруг bash-подпроцесса Rediaccfile ограничивает чтение файловой системы только директорией секретов текущей сети, поэтому cat /var/run/rediacc/secrets/<other>/X из вредоносного Rediaccfile не срабатывает с EACCES на уровне ядра.
Два дополнительных шаблона закрывают граничные случаи:
- Не встраивайте учётные данные продакшена в саму файловую систему репозитория.
.envфайл, коммитенный в образ, или учётные данные, сохранённые в томе во времяup(), рефлинкиются в форк. Функция секретов для каждого репозитория защищает только значения, которые вы храните в плоскости секретов. Она не может постфактум защитить байты, которые уже живут внутри LUKS-образа. Для существующих репо с встроенными.envфайлами поднимите их в секреты для каждого репозитория вручную. - Ограничьте исходящий сетевой трафик форка с помощью eBPF egress-фильтрации так, чтобы форк мог достигать только localhost и явных конечных точек песочницы. Сетевая изоляция Rediacc для каждого репозитория является основой; allowlist исходящего трафика для каждого форка не построен сегодня, но путь открыт.
Rediacc обрабатывает инъекцию во время развертывания, кросс-форк изоляцию и кросс-репо изоляцию. Половина «не встраивайте в образ» лежит на вас.
Быстрые рецепты
Разрешить агенту ротацию одного облачного токена
# Под вашей учётной записью, перед запуском агента:
export REDIACC_ALLOW_CONFIG_EDIT='/credentials/cfDnsApiToken'
claude-code # или cursor, gemini и т. д.
Теперь агент может выполнить config field rotate /credentials/cfDnsApiToken --new …, но по-прежнему не может редактировать /credentials/ssh/privateKey или открыть интерактивный редактор.
Разрешить агенту широкую сессию редактирования конфигурации
export REDIACC_ALLOW_CONFIG_EDIT='*'
claude-code
Агент может открыть rdc config edit, использовать --reveal и запустить field rotate. Каждое действие по-прежнему записывается в журнал аудита с actor.kind: agent и сигналом CLAUDECODE.
Узнать, какие поля агент может трогать
rdc config field list --sensitive --output json
Возвращает каждый шаблон указателя, его тип (secret / credential / pii / identifier) и входит ли он в HMAC-конверт на стороне сервера.
Смотрите также
- Обзор интеграции AI-агентов: общий тур
- Настройка Claude Code: шаблон интеграции
- Конверт JSON-вывода: машиночитаемые ответы
- Зашифрованное хранилище конфигурации: криптографическое исполнение на стороне сервера
- Безопасность аккаунта: позиция безопасности оператора