RunCommandTool и безопасный режим (Bubblewrap)
В этом документе описаны RunCommandTool (тул агента для выполнения shell-команд) и работа безопасного режима через Bubblewrap (bwrap) в Linux. Режим unsafe использует субпроцесс ОС напрямую и доступен на всех платформах.
1. Что это
RunCommandTool
RunCommandTool выполняет shell-команды (например, ls -la, python script.py). Два режима:
- Safe (по умолчанию): Команда выполняется в песочнице Bubblewrap (bwrap): минимальный вид файловой системы (только чтение /usr, привязка workspace), пространства имён, без сети по умолчанию. Только Linux; требуется установленный
bwrap. Еслиbwrapне найден, тул возвращает ошибку со ссылкой на инструкцию по установке. - Unsafe: Команда выполняется через ОС (asyncio subprocess). Можно задать workspace_path, чтобы процесс использовал эту директорию как текущую, а пути в аргументах не могли выйти за её пределы. Работает в Windows, macOS, Linux.
Итого: safe (по умолчанию) = изоляция bwrap (Linux); unsafe = субпроцесс ОС (все платформы).
2. Как это работает
Поток RunCommandTool
- Конфиг: В глобальной секции
tools:или у агента:workspace_path(опционально),mode("safe"или"unsafe"),timeout_seconds,include_paths(опциональный список разрешённых команд/путей),exclude_paths(опциональный список запрещённых команд/путей). Режим по умолчанию - safe. Если RunCommandTool используется где угодно (глобально или у любого агента) иworkspace_pathне задан для эффективного конфига, сервер создаёт директорию./workspaceрядом сconfig.yamlи использует её как рабочую. - LLM: Агент передаёт в тул строку
command(иreasoning). - Проверка: Если заданы
include_pathsилиexclude_paths, тул проверяет, что исполняемый файл команды и пути в аргументах разрешены. Команды сопоставляются по имени (например,"ls") или по полному пути (например,/usr/bin/ls). include_paths имеет приоритет над exclude_paths: если путь есть в обоих списках, он разрешён. - Unsafe: Тул разрешает
workspace_path(если задан), проверяет пути в аргументах, затем запускаетsh -c "<command>"сcwd=workspace_pathи таймаутом. Возвращает форматированные stdout, stderr и код возврата. - Safe: Тул проверяет наличие
bwrap(например,which bwrap). Если нет - возвращает ошибку со ссылкой на установку Bubblewrap. Если есть: - Если в конфигурации тула заданы
include_pathsилиexclude_paths, OverlayFS монтируется один раз при старте сервера (не на каждую команду):- Сервер проверяет глобальный
tools:и списокtoolsкаждого агента; если RunCommandTool используется где угодно сmode: "safe"и заданыinclude_paths/exclude_paths, OverlayFSManager создаёт overlay-файловые системы: - Создаёт временные директории для слоёв overlay (lowerdir, upperdir, workdir)
- Монтирует исходные директории как нижний слой (только чтение)
- Создаёт whiteout-файлы в верхнем слое для исключённых бинарников
- Монтирует overlay и сохраняет пути монтирования
- Эти монтирования переиспользуются для всех выполнений команд в течение жизни сервера
- Сервер проверяет глобальный
- В рантайме тул использует заранее инициализированные монтирования OverlayFS из OverlayFSManager
- Это ограничивает доступные в песочнице бинарники на уровне файловой системы, в том числе команды, вызываемые скриптами
- Если ни
include_paths, ниexclude_pathsне заданы, используются монтирования по умолчанию (только чтение/usrи т.д.) - При остановке сервера все монтирования OverlayFS автоматически размонтируются, временные директории удаляются
- Запускает команду через
bwrapс настроенными монтированиями и таймаутом. Возвращает форматированные stdout, stderr, код возврата.
Безопасный режим: минимальные настройки по умолчанию (bwrap)
Безопасный режим использует минимальную, но достаточную настройку bwrap, чтобы песочница работала из коробки:
- Файловая система по умолчанию (когда
include_pathsне задан): Привязка/usrтолько для чтения; симлинки для/bin,/lib,/lib64;--proc /proc,--dev /dev; записываемая директория workspace, привязанная как/workspace(изworkspace_path, если задан, иначе временная или текущая рабочая директория). - Ограниченная файловая система (когда заданы
include_pathsилиexclude_paths): Используется OverlayFS для отфильтрованного вида файловой системы: - Инициализация: OverlayFS инициализируется один раз при старте сервера, если RunCommandTool используется с
mode: "safe"где угодно (глобальныйtools:илиtoolsлюбого агента). Пути (include_paths/exclude_paths) могут быть не заданы; тогда overlay-монтирования не создаются, но менеджер готов. Если пути заданы, создаются overlay-монтирования для этих директорий. - Нижний слой: Исходные директории (например,
/usr/bin) смонтированы только для чтения - Верхний слой: Временная директория с whiteout-файлами для exclude_paths
- Объединённый слой: OverlayFS-монтирование, объединяющее нижний и верхний слои, скрывая исключённые файлы
- Например, при
include_paths: ["ls", "cat"]иexclude_paths: ["rm"], если все в/usr/bin:- Нижний слой:
/usr/bin(только чтение, все бинарники) - Верхний слой: Содержит whiteout-файл
.wh.rm, скрывающийrm - Объединённый: overlay
/usr/binпоказываетlsиcat, но неrm
- Нижний слой:
- Overlay монтируется в bwrap по исходному пути
- Системные директории (
/lib,/usr/lib,/lib64,/usr/lib64) всегда монтируются для зависимостей (shared libraries) - Переиспользование: Одни и те же overlay-монтирования используются для всех выполнений команд (без накладных расходов на команду)
- Очистка: При остановке сервера все OverlayFS-монтирования размонтируются, временные директории удаляются
- Это гарантирует, что команды, вызываемые из скриптов (например,
bash script.sh, вызывающийrm), тоже ограничены: еслиrmскрыт whiteout, он недоступен в песочнице - Выполнение: Процесс запускается с
--chdir /workspace,--unshare-all,--die-with-parent; команда выполняется как/bin/sh -c "<command>". - Таймаут: Задаётся тулом (subprocess timeout) после
timeout_seconds.
Это даёт изоляцию (пространства имён, ограниченная файловая система) без дополнительной настройки. При использовании include_paths/exclude_paths песочница использует OverlayFS для ограничения бинарников на уровне файловой системы, так что скрипты не могут выполнить запрещённые команды даже при попытке.
Детали реализации OverlayFS
Как работает OverlayFS:
- Нижний слой (только чтение): Исходная файловая система (например,
/usr/binсо всеми бинарниками) - Верхний слой (запись): Whiteout-файлы (
.wh.<имя_файла>), скрывающие файлы нижнего слоя - Рабочая директория: Временная директория для атомарных операций OverlayFS
- Объединённое монтирование: Общий вид, в котором исключённые файлы скрыты
Whiteout-файлы:
- Формат: символьное устройство с major/minor 0/0 или обычный файл
.wh.<исходное_имя> - При встрече whiteout OverlayFS скрывает соответствующий файл из нижнего слоя
- Это позволяет исключать отдельные файлы из директории, не исключая всю директорию
Управление жизненным циклом:
- Старт сервера: OverlayFS инициализируется OverlayFSManager в фазе FastAPI
lifespanstartup - Конфигурация: Конфиг RunCommandTool берётся из глобального
tools:или из любого агента (выигрывает первый кандидат сmode: "safe"). Если вездеmode: "unsafe", overlay не инициализируется. Если хотя бы один конфиг (глобальный или агента) имеетmode: "safe", overlay инициализируется (include_paths/exclude_paths могут быть не заданы; тогда 0 монтирований). - Инициализация: При наличии хотя бы одного safe-конфига (глобального или у агента)
- Рантайм: Заранее инициализированные монтирования переиспользуются для всех выполнений команд
- Остановка сервера: Все OverlayFS-монтирования размонтируются, временные директории удаляются в фазе FastAPI
lifespanshutdown
Преимущества:
- Нативный механизм ядра (не нужен SUID)
- Точное исключение файлов внутри директорий
- Удобная работа с bwrap
- Эффективность: монтирования создаются один раз при старте, переиспользуются для всех команд
- Автоматическая очистка при остановке сервера
3. Справочник конфигурации
Все параметры опциональны. Задаются в глобальной секции tools: или у агента.
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
workspace_path |
str | None | Директория для cwd (unsafe) или workspace bwrap (safe). В safe-режиме эта директория привязывается как /workspace внутри песочницы. Если при использовании RunCommandTool параметр не задан, сервер создаёт директорию ./workspace рядом с config.yaml и использует её. |
mode |
str | "safe" |
"safe" или "unsafe". Safe использует bwrap (только Linux); unsafe - локальный субпроцесс. |
timeout_seconds |
int | 60 | Максимальное время выполнения в секундах. |
include_paths |
list[str] | None | Разрешённые команды/пути. Если задано, выполняться могут только команды из этого списка. Сопоставление по имени (например, "ls") или полному пути (например, "/usr/bin/ls"). Пути в аргументах команды тоже проверяются. Имеет приоритет над exclude_paths (один и тот же путь в обоих - разрешён). |
exclude_paths |
list[str] | None | Исключённые команды/пути. Если задано, они запрещены, если не указаны также в include_paths. |
Параметры тула (от LLM / схемы): reasoning (str), command (str, полная командная строка).
Пример (unsafe):
Пример (safe, Linux с установленным bwrap):
Пример (с include_paths/exclude_paths - ограничение разрешённых команд):
tools:
run_command_tool:
workspace_path: "/tmp/agent_workspace"
mode: "unsafe"
timeout_seconds: 60
include_paths:
- "ls"
- "cat"
- "/usr/bin/python3"
- "/tmp/agent_workspace" # Доступ к директории workspace
exclude_paths:
- "rm"
- "/usr/bin/rm"
Установка Bubblewrap (для безопасного режима)
Безопасный режим требует наличия bwrap в системе. Если он не установлен, тул возвращает сообщение об ошибке со ссылкой на инструкцию по установке.
- Установка: См. Bubblewrap - Installation. В Debian/Ubuntu:
apt install bubblewrap. В Fedora:dnf install bubblewrap. В Arch:pacman -S bubblewrap. - Docker: В Docker-образе проекта bubblewrap ставится через
apt, поэтому безопасный режим работает без дополнительных шагов.
4. Аналоги и альтернативы
Режим Unsafe (ОС)
Unsafe использует субпроцесс ОС и опционально workspace_path; работает на всех платформах. Используйте, когда нужна только граница по директории или когда bwrap недоступен (например, Windows, macOS).
Bubblewrap + OverlayFS (безопасный режим)
bubblewrap - лёгкая непривилегированная песочница на базе пространств имён Linux и bind-монтирований. Используется в Flatpak и др. Безопасный режим сочетает bwrap с OverlayFS для точного управления файловой системой:
- bwrap даёт изоляцию пространств имён (PID, UTS, IPC, NET, MNT, USER, CGROUP, TIME)
- OverlayFS даёт исключение на уровне файлов через whiteout-файлы
- Вместе это позволяет монтировать директории, исключая отдельные файлы, без SUID-бинарников
Безопасный режим строит минимальное окружение, в котором команды выполняются изолированно с одной записываемой директорией workspace и отфильтрованным доступом к бинарникам.
5. Замечания по безопасности
- Unsafe: Выполняется от того же пользователя, что и агент. Проверка путей ограничивает доступ к
workspace_path; используйте таймаут, чтобы избежать зависаний. - Safe: Использует bwrap для изоляции пространств имён и файловой системы. Песочница не является полной границей безопасности; используйте как слой снижения рисков. Убедитесь, что
workspace_pathуказывает на выделенную рабочую директорию, а не на чувствительную.
6. Кратко
| Элемент | Описание |
|---|---|
| RunCommandTool | Выполняет shell-команды; unsafe = субпроцесс ОС (все платформы); safe = песочница bwrap (Linux, требуется bwrap). |
| bwrap | Должен быть установлен для безопасного режима. Установка: Bubblewrap - Installation. |
| Минимальные умолчания | Безопасный режим использует минимальную настройку bwrap: ro-bind /usr, workspace как /workspace, unshare-all, таймаут. |
| OverlayFS | При заданных include_paths/exclude_paths использует OverlayFS с whiteout-файлами для исключения отдельных бинарников из директорий. |