Перейти к содержимому
13 мин чтения

OpenClaw в Docker: песочница и права доступа для агента с доступом к shell

openclawdockerпесочницабезопасность ai-агентовизоляцияправа доступаai-агенты

Коротко. Песочница в OpenClaw выключена по умолчанию: пока вы её не включили, агент выполняет команды прямо на хосте от имени того пользователя, под которым запущен. Включается она одним ключом agents.defaults.sandbox.mode в файле ~/.openclaw/openclaw.json и по умолчанию использует Docker. Важно понимать три вещи. Первая: в контейнер уезжает только выполнение инструментов — сам процесс Gateway всегда остаётся на хосте. Вторая: настройками песочницы, списком разрешённых инструментов и режимом прав сессии управляют три независимых механизма, и «агент всё равно что-то может» почти всегда означает, что вы закрутили не тот. Третья, и самая обидная: изменение конфига не влияет на уже запущенные контейнеры — без openclaw sandbox recreate вы будете смотреть в правильный конфиг и получать старое поведение. Ниже — рабочая минимальная конфигурация, команда проверки того, что реально применилось, и разбор мест, где изоляция протекает по вашему же согласию.

На чём это проверено

Все ключи конфигурации, команды, значения по умолчанию и списки заблокированных путей сверены с официальной документацией и релизными данными проекта 8 сентября 2026 года. Актуальный релиз на эту дату — OpenClaw 2026.9.2 (опубликован 5 сентября 2026 года; в реестре npm канал latest2026.9.2, канал extended-stable2026.6.34). Проект выпускает релизы часто, поэтому перед копированием в боевой конфиг сверьтесь с docs.openclaw.ai.

Статья предполагает, что OpenClaw уже установлен и отвечает: провайдер подключён, модель выбрана. Если нет — начните с материалов как установить OpenClaw и первичная настройка OpenClaw, а сюда возвращайтесь, когда дойдёт до вопроса «а что этот агент вообще может сделать с моим сервером».

Что изолируется, а что нет

Формулировка из документации прямая, и её стоит принять до того, как вы начнёте что-то настраивать: песочница — не идеальная граница безопасности, она существенно ограничивает доступ к файлам и процессам, когда модель делает глупость. Это разумная цель. Это не защита от целенаправленной атаки на ваш сервер.

В песочницу уезжает:

  • выполнение инструментов — exec, read, write, edit, apply_patch, process и подобные;
  • опциональный браузер в песочнице (agents.defaults.sandbox.browser).

В песочницу не уезжает:

  • сам процесс Gateway — он всегда на хосте;
  • нативные плагины: они работают внутри процесса Gateway и разделяют его границу доверия;
  • всё, что явно выпущено наружу через tools.elevated (об этом ниже).

Три независимых рычага — и почему их путают

Это главная развилка всей темы. В OpenClaw три разных механизма, и они отвечают на три разных вопроса:

  1. Песочница (agents.defaults.sandbox.*) — где выполняются инструменты: в контейнере или на хосте.
  2. Политика инструментов (tools.*, tools.sandbox.tools.*) — какие инструменты вообще доступны агенту.
  3. Elevated (tools.elevated.*) — аварийный выход только для exec: разрешить конкретное выполнение на хосте в обход обычной песочницы.

Практический вывод: если агент делает то, чего вы не хотите, сначала определите, какой из трёх рычагов за это отвечает. Запрет инструмента не переносит его выполнение в контейнер, а включение песочницы не отбирает у агента инструмент. Половина вопросов вида «я же настроил, почему не работает» — это попытка закрутить не тот механизм.

Шаг 1. Собрать образ песочницы

Образ по умолчанию — openclaw-sandbox:bookworm-slim. Его нужно собрать заранее: OpenClaw не подставляет молча обычный debian:bookworm-slim, если нужного образа нет. Запуск упадёт сразу с инструкцией по сборке — потому что штатный образ несёт python3, на котором работают помощники записи и правки файлов внутри песочницы.

Если вы ставили OpenClaw глобально через npm (исходников на диске нет), соберите образ так:

docker build -t openclaw-sandbox:bookworm-slim - <<'DOCKERFILE'
FROM debian:bookworm-slim
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
  bash ca-certificates curl git jq python3 ripgrep \
  && rm -rf /var/lib/apt/lists/*
RUN useradd --create-home --shell /bin/bash sandbox
USER sandbox
WORKDIR /home/sandbox
CMD ["sleep", "infinity"]
DOCKERFILE

Если вы работаете из клона репозитория, есть готовый скрипт scripts/sandbox-setup.sh — в npm-пакет он не входит.

Обратите внимание на две строки. USER sandbox — контейнер работает не от root. И в образе нет Node: если вашему навыку нужен Node или другой рантайм, либо соберите свой образ, либо ставьте через sandbox.docker.setupCommand — но последнее требует сетевого доступа, записываемого корня и пользователя root, то есть ровно тех трёх послаблений, ради отмены которых вы всё это и затеяли. Лучше собрать образ. Для более функционального варианта в проекте есть Dockerfile.common с curl, jq, Node 24, pnpm, python3 и git — собирается в образ openclaw-sandbox-common:bookworm-slim.

Шаг 2. Включить песочницу

Настройки живут в ~/.openclaw/openclaw.json под ключом agents.defaults.sandbox (переопределения для отдельного агента — в agents.entries.*.sandbox). Поведением управляют три независимые настройки:

НастройкаКлючЗначенияПо умолчанию
Режимsandbox.modeoff, non-main, alloff
Областьsandbox.scopeagent, session, sharedagent
Бэкендsandbox.backenddocker, podman, ssh, openshelldocker

Про mode есть неочевидный момент, который в документации помечен как «типичный сюрприз». Режим non-main изолирует все сессии, кроме основной сессии агента (её ключ всегда agent:<agentId>:main и не настраивается). Групповые и канальные сессии используют собственные ключи — то есть всегда считаются не-основными и всегда попадают в песочницу. Если агент отвечает в общем чате, non-main уже даёт вам основную защиту, а вы продолжаете работать с ним напрямую без контейнера.

Такие края — где настройка называется одним, а применяется к другому — и составляют основную часть работы. Разбираться в них на сервере, где агент уже что-то делает с вашими данными, дорого: цена ошибки здесь не «сломалось», а «не защищено, и мы об этом не знаем». Если периметр нужно закрыть не в тестовом контуре, а в бою, мы проверим доступы вашего агента и попробуем выйти из его песочницы — проверка на проникновение даёт ответ быстрее, чем выяснение границ механизмов методом проб.

Минимальная строгая конфигурация, которая сохраняет ограничительные настройки по умолчанию и делает рабочую папку агента доступной только на чтение:

{
  "agents": {
    "defaults": {
      "sandbox": {
        "mode": "all",
        "backend": "docker",
        "scope": "session",
        "workspaceAccess": "ro",
        "docker": {
          "image": "openclaw-sandbox:bookworm-slim",
          "readOnlyRoot": true,
          "tmpfs": ["/tmp", "/var/tmp", "/run"],
          "network": "none",
          "capDrop": ["ALL"]
        }
      }
    }
  }
}

Значения network: "none", readOnlyRoot: true и capDrop: ["ALL"] — это и есть настройки Docker-бэкенда по умолчанию; в конфиге выше они выписаны явно, чтобы их было видно при code review, а не чтобы что-то изменить. Дополнительно OpenClaw создаёт контейнеры песочницы с init-процессом и флагом no-new-privileges. При workspaceAccess: "ro" рабочая папка агента монтируется только на чтение в /agent, попытки записи в неё отклоняются, а перечисленные пути tmpfs остаются записываемыми.

Отдельно проговорим сеть. По умолчанию у локальных контейнеров песочницы сети нет вообще. Это сильное ограничение и его стоит подержать как можно дольше: агент без egress не выгрузит наружу то, что прочитал.

Шаг 3. Пересоздать контейнеры — та самая ошибка

Если вы запомните из статьи одну команду, пусть это будет она. Правка конфига не влияет на уже запущенные контейнеры. Существующие рантаймы продолжают работать со старыми настройками. Простаивающие удаляются только по таймауту prune.idleHours (по умолчанию 24 часа) и prune.maxAgeDays (по умолчанию 7 дней), а у регулярно используемого агента контейнер может не простаивать никогда — и жить со старым конфигом сколько угодно долго.

openclaw sandbox recreate --all

Команда удаляет старые рантаймы, и при следующем обращении к агенту они пересобираются по текущему конфигу. Точечные варианты:

openclaw sandbox recreate --agent mybot
openclaw sandbox recreate --session "agent:main:main"
openclaw sandbox recreate --all --force

Ровно один из флагов --all, --session или --agent; --force пропускает подтверждение. Пересоздавать нужно после смены образа, любых ключей agents.defaults.sandbox.* и после правки setupCommand.

Шаг 4. Проверить, что применилось на самом деле

Не верьте конфигу — спросите систему. Отдельная команда показывает эффективный режим, область, доступ к рабочей папке, действующую политику инструментов в песочнице и открытые elevated-шлюзы, причём с указанием ключей конфига, которые надо править:

openclaw sandbox explain
openclaw sandbox explain --session agent:main:main
openclaw sandbox explain --agent work
openclaw sandbox explain --json

Посмотреть, что вообще запущено, — openclaw sandbox list (со статусом, бэкендом, совпадением с конфигом, возрастом и временем простоя). Общая диагностика — openclaw doctor, а openclaw doctor --fix дополнительно чинит часть находок, включая перенос устаревших файлов реестра песочниц в базу состояния.

Доступ к рабочей папке: три значения, которые решают многое

ЗначениеЧто происходит
none (по умолчанию)Инструменты читают и пишут в изолированную папку песочницы под ~/.openclaw/sandboxes. Рабочая папка агента не видна вообще.
roРабочая папка агента монтируется только на чтение в /agent; write, edit и apply_patch отключаются.
rwРабочая папка агента монтируется на чтение и запись в /workspace.

Значение по умолчанию здесь — самое строгое, и это правильная отправная точка. Повышайте до ro, когда агенту действительно нужно видеть ваши файлы, и до rw — только когда он должен их менять.

Проброс папок: где изоляция протекает с вашего согласия

Когда одному агенту нужна не только его рабочая папка, используются bind-монтирования в формате хост:контейнер:режим:

{
  "agents": {
    "entries": {
      "research": {
        "workspace": "/srv/openclaw/research-workspace",
        "sandbox": {
          "workspaceAccess": "rw",
          "docker": {
            "binds": [
              "/srv/shared/reference:/reference:ro",
              "/srv/shared/drafts:/drafts:rw"
            ],
            "dangerouslyAllowExternalBindSources": true
          }
        }
      }
    }
  }
}

Здесь важны четыре факта, каждый из которых кого-нибудь уже подводил:

  • Bind пробивает песочницу. Смонтированное видно внутри контейнера ровно с тем режимом, который вы указали.
  • Если режим не указан, по умолчанию будет запись. Для исходников и секретов всегда пишите :ro явно.
  • Режим bind и workspaceAccess независимы. Смена workspaceAccess не превращает ro-проброс в rw и наоборот.
  • scope: "shared" игнорирует пер-агентные пробросы — применяются только глобальные. Для пер-агентных binds держите scope в значении agent или session.

По умолчанию OpenClaw блокирует опасные источники: системные пути (/etc, /proc, /sys, /dev, /root, /boot), каталоги сокета Docker (/run, /var/run и варианты с docker.sock) и типовые каталоги учётных данных в домашней директории (~/.aws, ~/.docker, ~/.gnupg, ~/.netrc, ~/.npm, ~/.ssh, ~/.config, ~/.cargo). Заблокированы и цели, перекрывающие зарезервированные точки монтирования /workspace и /agent. Источники вне разрешённых корней требуют явного dangerouslyAllowExternalBindSources: true — флаг назван так не для красоты.

Проверка источника выполняется дважды: сначала по нормализованному пути, затем повторно после разрешения через ближайшего существующего родителя — так что подмена через симлинк на родительском каталоге не проходит, даже если конечного файла ещё нет.

И отдельной строкой: проброс /var/run/docker.sock фактически отдаёт песочнице управление хостом. Это не «ещё один том» — это конец изоляции. Делайте это только осознанно и никогда «чтобы заработало».

Режимы прав сессии

Параллельно с песочницей у каждой сессии есть режим прав: он задаёт границу по файловой системе и то, кто согласует повышение при выполнении команд.

РежимФайловая системаКто согласует повышение exec
read-onlyЧтение в пределах корня сессии; изменяющие инструменты скрытыНикто; exec запрещён
guardedЧтение и запись в пределах корня сессииЧеловек, после быстрого прохода по белому списку
workspaceЧтение и запись в пределах корня сессииПроверка моделью, с откатом на человека
fullНеограниченный доступ к файловой системеНикто

Режим full требует прав operator.admin, остальные — operator.write. Менять режим можно прямо во время задачи через меню Permissions в поле ввода. При смене режима ожидающие согласования из старого режима отменяются, а не выдаются; уже сделанные записи и запущенные процессы не откатываются.

Практический режим для повседневной работы — guarded: агент читает и пишет в своей папке, а всё, что выходит за рамки белого списка команд, приходит к вам на подтверждение.

Политика инструментов и ловушка «exec разрешён, write запрещён»

Политика инструментов отвечает на вопрос «какие инструменты вообще существуют для этого агента». Правила короткие:

  • deny всегда побеждает;
  • если allow непустой, всё остальное считается заблокированным;
  • политика инструментов — жёсткий стоп: команда /exec не может переопределить запрещённый инструмент exec.

А теперь ловушка, которая стоит отдельного абзаца. Политика фильтрует инструменты по имени и не смотрит на побочные эффекты внутри exec. Если exec разрешён, то запрет write, edit и apply_patch не делает shell-команды доступными только на чтение — агент просто напишет файл через оболочку. Конфигурация «разрешаем exec, запрещаем запись» выглядит безопасной в конфиге и не является таковой в реальности. Настоящий read-only-агент требует запрета группы group:runtime (это exec, process, code_execution) вместе с изменяющими файловыми инструментами — либо отдельной границы на уровне файловой системы песочницы.

Группы задаются сокращениями group:*: group:fs — это read, write, edit, apply_patch; group:webweb_search, x_search, web_fetch; и так далее. Когда сессия изолирована, добавляется вторая решётка — tools.sandbox.tools.allow и tools.sandbox.tools.deny. Про неё стоит помнить, если у вас подключены MCP-серверы: в изолированных сессиях их инструменты нужно разрешить отдельно, иначе агент увидит только встроенные.

Проверить постфактум, что именно отрезалось, можно по журналу: Gateway пишет записи аудита agents/tool-policy, когда политика убирает инструменты или блокирует вызов. Смотреть — командой openclaw logs; там же видно метку правила, ключ конфига и имена затронутых инструментов.

Elevated: осознанная дыра

Elevated не выдаёт дополнительных инструментов — он влияет только на exec. Если сессия обычно изолирована, /elevated on выполняет команду вне песочницы (согласования при этом могут по-прежнему применяться), а /elevated full отключает согласования exec для сессии. Шлюзы: tools.elevated.enabled и белые списки отправителей tools.elevated.allowFrom.<provider>.

Два ограничения, которые полезно знать: elevated не переопределяет разрешения и запреты инструментов, и он не может обойти песочницу, обязательную по роли создателя сессии. Если вы задали именованной операторской роли политику sandbox: "required", её сессии изолируются независимо от режима агента, требование неизменяемо для сессии, а при недоступном бэкенде система отказывает, а не откатывается на выполнение на хосте. Это самая жёсткая из доступных настроек, и для агента, которым пользуется кто-то кроме вас, она обычно и нужна.

Если сам Gateway живёт в контейнере

Отдельный случай, дающий неочевидные ошибки. Если вы разворачиваете Gateway как Docker-контейнер, он управляет соседними контейнерами песочницы через сокет Docker на хосте. Отсюда требование к путям: в openclaw.json ключ workspace должен содержать абсолютный путь хоста, а не внутренний путь контейнера Gateway, — демон Docker разбирает пути в пространстве имён хоста. Кроме того, контейнеру Gateway нужно дать идентичный маппинг тома, чтобы тот же путь резолвился и изнутри. Несовпадение проявляется как EACCES при записи файлов рабочей области. И там же — правило, которое не стоит нарушать: не монтируйте сокет Docker хоста в контейнеры агентской песочницы.

Чек-лист перед тем, как дать агенту доступ к shell

  1. Образ openclaw-sandbox:bookworm-slim собран.
  2. sandbox.modeall или как минимум non-main, если агент отвечает в групповых чатах.
  3. workspaceAccess — минимально необходимый: none, иначе ro, и только при реальной нужде rw.
  4. network оставлен в none, пока не доказано обратное.
  5. Список docker.binds просмотрен построчно; у всех чувствительных пробросов явный :ro; сокета Docker в списке нет.
  6. Выполнен openclaw sandbox recreate --all после последней правки конфига.
  7. openclaw sandbox explain показывает то, что вы ожидали, а не то, что вы написали.
  8. Режим прав сессии осознанно выбран; full не является режимом по умолчанию.
  9. Если нужен read-only-агент — запрещён group:runtime, а не только файловые инструменты.
  10. tools.elevated.allowFrom перечисляет конкретных отправителей, а не открыт всем.

Когда не стоит делать это самому

Всё описанное выше делается руками за вечер — если у вас уже есть Docker, вы читаете JSON без раздражения и готовы потом раз в несколько недель пересобирать образ под новые релизы. Это честная оценка: тут нет скрытого шага, который мы намеренно не назвали.

Сложность не в первичной настройке, а в эксплуатации. Образ песочницы устаревает вместе с базовым Debian. Контейнеры молча живут со старым конфигом, пока кто-нибудь не вспомнит про recreate. Каждый новый навык агента приносит соблазн добавить ещё один bind «на время», и через полгода в списке пробросов оказывается половина файловой системы. А ошибка в конфигурации песочницы не проявляется как поломка — она проявляется как отсутствие защиты, о котором вы узнаёте по факту.

Если держать этот слой в порядке некому, мы возьмём на себя серверы, образы и обновления под агентом — контейнеры пересобираются по расписанию, конфиг под контролем версий, доступы ревизуются, а не накапливаются. Что входит в сопровождение и во что оно обходится — на странице тарифов. Если же вопрос стоит уже, а агент работает в бою, начните с проверки текущего периметра: она обычно окупается тем, что находит один лишний rw-проброс, о котором все забыли.

Дальше по теме — тюнинг OpenClaw: маршрутизация моделей, память и контроль расходов.