Представляем sandbox-runtime от Anthropic: песочница на уровне ОС для ИИ-агентов без контейнеров
В этой статье мы обсудим недавно ставший популярным опенсорсный sandbox-runtime (srt) от Anthropic — песочницу на уровне ОС, лежащую в основе изолированного инструмента bash в Claude Code. Anthropic sandbox-runtime ограничивает файлы, к которым может обращаться процесс, и хосты, к которым он может подключаться. При этом контейнер не запускается. Инструмент также не привязан к Claude Code. Ваши собственные агенты, локальные MCP-серверы и обычные программы командной строки могут работать внутри него.
Кратко
- Размер: пакет npm
@anthropic-ai/sandbox-runtimeверсии 0.0.81, около 11,4 МБ в распакованном виде, лицензия Apache-2.0, Node.js 22.12+. - Работает на: любом компьютере разработчика или CI-сервере под macOS или Linux. macOS использует Seatbelt; для Linux нужны bubblewrap, socat и ripgrep. Windows находится на стадии альфа-тестирования.
- Производительность: по внутренним данным Anthropic, песочница сократила количество запросов разрешений Claude Code на 84% (самооценка).
- Лучшее: на 84% меньше запросов разрешений, при этом ограничения файловой системы и сети применяются ко всему дереву процессов.
- Худшее: это всё ещё бета-версия исследовательского превью, а поддержка Windows находится на стадии альфа-тестирования.
Что такое Anthropic sandbox-runtime?
Anthropic sandbox-runtime — это опенсорсный инструмент, который запускает любой процесс с ограничениями файловой системы и сети. Установите его с помощью npm install -g @anthropic-ai/sandbox-runtime, а затем добавьте srt перед командой. Он работает как CLI-инструмент и как библиотека TypeScript.
Как sandbox-runtime работает в macOS, Linux и Windows?
srt использует собственные примитивы изоляции каждой операционной системы. Ограничения распространяются на всё дерево процессов, включая скрипты и дочерние процессы.
- macOS:
sandbox-execс динамически создаваемыми профилями Seatbelt. Требуется только ripgrep. - Linux: bubblewrap с удалённым сетевым пространством имён. Также нужны socat и ripgrep.
- Windows (альфа-версия): выделенная учётная запись
srt-sandbox, фильтр исходящего трафика Windows Filtering Platform и явные ACL для файлов.
Трафик выходит наружу только через HTTP- и SOCKS5-прокси, работающие на хосте. В Linux эти прокси находятся за Unix-сокетами, подключёнными к песочнице через bind mount. В macOS профиль Seatbelt разрешает только один локальный порт. Затем прокси применяют ваш список разрешённых и запрещённых доменов.
Зачем нужны изоляция файловой системы и сети одновременно?
Команда Anthropic утверждает, что одна граница без другой не обеспечивает защиту. Без сетевой изоляции агент, подвергшийся атаке через внедрение промпта, мог бы похитить SSH-ключи. Без изоляции файловой системы он мог бы выйти из песочницы и получить доступ к сети.
Настройки srt по умолчанию следуют этой логике. Чтение разрешено везде, если оно не запрещено явно. Запись запрещена везде, если она не разрешена явно. Доступ к сети запрещён, если домен не добавлен в список разрешённых.
Как изолировать MCP-сервер или собственного агента?
Для MCP-сервера замените command в .mcp.json с npx на srt. Исходную команду передайте как аргументы. Правила хранятся в ~/.srt-settings.json:
{
"network": { "allowedDomains": ["api.github.com", "*.npmjs.org"], "deniedDomains": [] },
"filesystem": { "denyRead": ["~/.ssh"], "allowWrite": ["."], "denyWrite": [".env"] }
}Для собственного агента библиотека предоставляет SandboxManager. Вызовите initialize(config), чтобы запустить прокси. Затем wrapWithSandbox() вернёт обёрнутую строку команды, которую можно запустить.
Что означает показатель 84%?
Anthropic сообщает, что изоляция сократила количество запросов разрешений на 84% при внутреннем использовании Claude Code. Это самооценка, а не внешний бенчмарк. Цель — уменьшить усталость от подтверждений. Разработчики, которые весь день нажимают «разрешить», перестают читать, что именно они разрешают. Фиксированная граница позволяет агенту свободно работать внутри неё и запрашивать разрешение только при её пересечении.
</button>
<button class="btn" id="fplay">Автовоспроизведение</button>
</div>
</div>
<div class="pane" id="p-sim">
<div class="sim">
<div>
<div class="card">
<h5>network.allowedDomains</h5>
<label class="chk"><input type="checkbox" id="d-anth" checked> anthropic.com</label>
<label class="chk"><input type="checkbox" id="d-npm"> *.npmjs.org</label>
<label class="chk"><input type="checkbox" id="d-gh"> github.com</label>
<h5 style="margin-top:12px">файловая система</h5>
<label class="chk"><input type="checkbox" id="f-ssh" checked> denyRead: ~/.ssh</label>
<label class="chk"><input type="checkbox" id="f-env" checked> denyWrite: .env</label>
</div>
</div>
<div>
<div class="cmds" id="cmds">
<button class="cmd" data-c="0">srt "cat README.md"</button>
<button class="cmd" data-c="1">srt "cat ~/.ssh/id_rsa"</button>
<button class="cmd" data-c="2">srt "curl anthropic.com"</button>
<button class="cmd" data-c="3">srt "curl example.com"</button>
<button class="cmd" data-c="4">srt "npm install"</button>
<button class="cmd" data-c="5">srt "echo KEY=1 >> .env"</button>
</div>
<div class="term" id="term" style="margin-top:10px"><span class="dim">Выберите команду. Измените конфигурацию, чтобы увидеть результат.</span></div>
<div class="why" id="why"></div>
</div>
</div>
</div>
<div class="pane" id="p-plat">
<div class="plat">
<div class="pc on" data-p="0"><h4>macOS</h4><span class="tag t-g">Поддерживается</span><ul><li>sandbox-exec</li><li>Профили Seatbelt</li><li>Требуется ripgrep</li></ul></div>
<div class="pc" data-p="1"><h4>Linux</h4><span class="tag t-g">Поддерживается</span><ul><li>bubblewrap</li><li>Без сетевого пространства имён</li><li>socat + ripgrep</li></ul></div>
<div class="pc" data-p="2"><h4>Windows</h4><span class="tag t-o">Альфа</span><ul><li>Учётная запись srt-sandbox</li><li>Фильтр исходящего трафика WFP</li><li>Однократная установка</li></ul></div>
</div>
<div class="desc pdetail" id="pdesc"></div>
</div>
<div class="pane" id="p-defs">
<div class="defs">
<div class="dc"><div class="kicker">Чтение</div><div class="big" style="color:#b5cc94">Разрешено</div><p>По умолчанию разрешено везде. Запретите отдельные области, например ~/.ssh, и снова разрешите их с помощью allowRead.</p></div>
<div class="dc"><div class="kicker">Запись</div><div class="big" style="color:#ef7a73">Запрещено</div><p>По умолчанию запрещена везде. Откройте отдельные пути, например "." и /tmp, с помощью allowWrite.</p></div>
<div class="dc"><div class="kicker">Сеть</div><div class="big" style="color:#ef7a73">Запрещено</div><p>По умолчанию доступа нет. Каждый хост должен соответствовать allowedDomains.</p></div>
</div>
<div class="bars" id="bars">
<div class="kicker" style="margin-bottom:4px">Запросы разрешений Claude Code (индексированные)</div>
<div class="bar"><div class="lb"><span>Без изоляции</span><span>100</span></div><div class="bg"><div class="fg" data-w="100" style="background:var(--muted)"></div></div></div>
<div class="bar"><div class="lb"><span>С изоляцией</span><span>16</span></div><div class="bg"><div class="fg" data-w="16" style="background:var(--orange)"></div></div></div>
<div class="note">На 84% меньше запросов во внутреннем использовании Anthropic (самооценка, инженерная публикация за октябрь 2025 года). Индексировано относительно 100.</div>
</div>
</div>
<div class="pane" id="p-cmp">
<div class="tblwrap">
<table>
<thead><tr><th></th><th>srt</th><th>Codex CLI</th><th>Docker Sandboxes</th><th>E2B</th></tr></thead>
<tbody>
<tr class="row"><td>Изоляция</td><td class="hl">Примитивы ОС</td><td>Примитивы ОС</td><td>microVM</td><td>Firecracker microVM</td></tr>
<tr class="row"><td>Запуск</td><td class="hl">Локально</td><td>Локально</td><td>Локально</td><td>Облако / BYOC</td></tr>
<tr class="row"><td>Контейнер или виртуальная машина</td><td class="hl">Нет</td><td>Нет</td><td>Да</td><td>Да</td></tr>
<tr class="row"><td>Сеть по умолчанию</td><td class="hl">Запретить всё</td><td>Отключена (переключатель)</td><td>Выбранная политика</td><td>Включена</td></tr>
<tr class="row"><td>Список разрешённых доменов</td><td class="hl">Шаблоны + порты</td><td>Не раскрыто</td><td>Шаблоны + порты</td><td>allowOut, шаблоны</td></tr>
<tr class="row"><td>Лицензия</td><td class="hl">Apache-2.0</td><td>Apache-2.0</td><td>Не раскрыто</td><td>Apache-2.0 (SDK)</td></tr>
</tbody>
</table>
</div>
</div>
<div class="ft"><span>Источники: github.com/anthropics/sandbox-runtime · anthropic.com/engineering · v0.0.81</span><span class="mtp">Создано Marktechpost</span></div>
</div>
<script>
(function(){
var R=document.getElementById('srt-x');
function post(){try{parent.postMessage({srtH:R.offsetHeight+40},'*')}catch(e){}}
var tabs=R.querySelectorAll('.tab');
tabs.forEach(function(b){b.addEventListener('click',function(){
tabs.forEach(function(x){x.classList.remove('on')});b.classList.add('on');
R.querySelectorAll('.pane').forEach(function(p){p.classList.remove('on')});
var t=b.getAttribute('data-t');document.getElementById('p-'+t).classList.add('on');
if(t==='defs')bars();if(t==='cmp')rows();setTimeout(post,60);
})});
// flow
var steps=[
['Ваш агент запускает команду','Агент, MCP-сервер или CLI-инструмент отправляет команду. Она не изменяется: srt лишь оборачивает её.',0,'act'],
['srt создаёт политику','srt загружает ~/.srt-settings.json (или встроенные настройки по умолчанию) и запускает HTTP- и SOCKS5-прокси на хосте.',1,'act'],
['ОС применяет границу','Seatbelt (macOS), bubblewrap (Linux) или фильтр WFP (альфа-версия Windows) применяет правила для файлов ко всему дереву процессов.',2,'act'],
['Весь трафик проходит через прокси','У песочницы нет прямого маршрута наружу. В Linux сетевое пространство имён удалено; прокси доступны через Unix-сокеты.',3,'act'],
['Разрешённый хост: соединение устанавливается','Хост из allowedDomains проходит проверку после того, как подтверждено, что он не разрешается в IP-адрес loopback или облачных метаданных.',4,'ok'],
['Неизвестный хост: заблокирован или запрошен','Запрещённый или отсутствующий в списке хост отклоняется, либо решение принимает callback запроса. Нарушение записывается в журнал, чтобы агент мог его прочитать.',4,'bad']
];
var fi=0,timer=null;
function draw(){
var s=steps[fi];var ns=R.querySelectorAll('.node');
ns.forEach(function(n,i){n.classList.remove('act','ok','bad');if(i<s[2])n.classList.add('act')});
ns[s[2]].classList.add(s[3]);
var pk=document.getElementById('pkt');pk.style.left=(s[2]*22)+'%';
pk.style.background=s[3]==='ok'?'#788c5d':s[3]==='bad'?'#d4504a':'#d97757';
document.getElementById('fdesc').innerHTML='<h4>Шаг '+(fi+1)+' из '+steps.length+': '+s[0]+'</h4>'+s[1];
}
document.getElementById('fnext').onclick=function(){fi=(fi+1)%steps.length;draw()};
document.getElementById('fprev').onclick=function(){fi=(fi-1+steps.length)%steps.length;draw()};
document.getElementById('fplay').onclick=function(){
if(timer){clearInterval(timer);timer=null;this.textContent='Автовоспроизведение';return}
this.textContent='Пауза';timer=setInterval(function(){fi=(fi+1)%steps.length;draw()},1800);
};
draw();
// sim
function on(id){return document.getElementById(id).checked}
var C=[
function(){return [1,'# Anthropic Sandbox Runtime (srt) ...','Чтение по умолчанию разрешено, и текущий каталог доступен для чтения.']},
function(){return on('f-ssh')?[0,'cat: ~/.ssh/id_rsa: Operation not permitted','~/.ssh находится в denyRead, поэтому ключ нельзя прочитать.']:[1,'-----BEGIN OPENSSH PRIVATE KEY----- ...','Если правило denyRead отсутствует, чтение открыто везде. Явно запрещайте доступ к секретам.']},
function(){return on('d-anth')?[1,'<html>...</html>','anthropic.com находится в allowedDomains, поэтому прокси перенаправляет запрос.']:[0,'Соединение заблокировано списком разрешённых сетевых адресов','Совпадений со списком нет: сеть по умолчанию запрещена.']},
function(){return [0,'Соединение заблокировано списком разрешённых сетевых адресов','example.com отсутствует в списке разрешённых.']},
function(){return on('d-npm')?[1,'пакеты установлены (иллюстративный вывод)','*.npmjs.org добавлен в список разрешённых, поэтому реестр доступен.']:[0,'npm ERR! network request to registry.npmjs.org failed\nСоединение заблокировано списком разрешённых сетевых адресов','Классический компромисс: если ограничения слишком строгие, установка завершается ошибкой.']},
function(){return on('f-env')?[0,'bash: .env: Operation not permitted','denyWrite имеет приоритет над allowWrite, поэтому .env остаётся защищённым внутри проекта.']:[1,'(записано)','"." находится в allowWrite, поэтому запись выполняется.']}
];
var busy=false;
R.querySelectorAll('.cmd').forEach(function(b){b.addEventListener('click',function(){
if(busy)return;busy=true;var r=C[+b.getAttribute('data-c')]();var t=document.getElementById('term');
t.innerHTML='<span class="p">$</span> '+b.textContent.replace(/</g,'<')+'\n<span class="dim">Выполняется внутри песочницы...</span>';
document.getElementById('why').textContent='';
setTimeout(function(){
t.innerHTML='<span class="p">$</span> '+b.textContent.replace(/</g,'<')+'\n<span class="'+(r[0]?'ok':'no')+'">'+(r[0]?'✓ ':'✗ ')+r[1].replace(/</g,'<')+'</span>';
document.getElementById('why').textContent=r[2];busy=false;post();
},650);
})});
// platforms
var P=['macOS использует встроенный инструмент sandbox-exec с профилями Seatbelt, создаваемыми для каждого запуска. Профиль разрешает только 1 локальный порт, на котором работают прокси srt. Нарушения можно в реальном времени просматривать в системном журнале.',
'Linux использует bubblewrap и полностью удаляет сетевое пространство имён. Доступ к прокси осуществляется через Unix-сокеты, подключённые к песочнице через bind mount. Для Ubuntu 24.04+ требуется изменить настройки AppArmor для пользовательских пространств имён.',
'Windows (альфа-версия) запускает команды от имени выделенной учётной записи srt-sandbox. Системный фильтр WFP блокирует исходящий трафик, кроме подключений к портам прокси. Для настройки требуется 1 установка с повышенными правами.'];
var pcs=R.querySelectorAll('.pc');
function pd(i){pcs.forEach(function(x){x.classList.remove('on')});pcs[i].classList.add('on');document.getElementById('pdesc').innerHTML='<h4>'+pcs[i].querySelector('h4').textContent+'</h4>'+P[i];post()}
pcs.forEach(function(c,i){c.addEventListener('click',function(){pd(i)})});pd(0);
function bars(){R.querySelectorAll('.fg').forEach(function(f){f.style.width='0';setTimeout(function(){f.style.width=f.getAttribute('data-w')+'%'},80)})}
function rows(){R.querySelectorAll('tr.row').forEach(function(r,i){r.classList.remove('in');setTimeout(function(){r.classList.add('in')},90*i+60)})}
window.addEventListener('load',post);window.addEventListener('resize',post);setTimeout(post,300);
})();
</script>
</body>
</html>
">
Настоящий компромисс: строгие списки разрешений против работающих агентов
Агенты для программирования делают больше, чем просто редактируют файлы. Они устанавливают зависимости, загружают документацию и обращаются к API. Если сделать список разрешений слишком строгим, npm install завершится с ошибкой. Если сделать его слишком широким, песочница будет мало что защищать. srt предлагает несколько настроек для поиска золотой середины:
- Шаблоны и порты: записи вроде
*.npmjs.orgилиapi.example.com:443. - Callback запроса: принимает решение по хостам, для которых нет правила, и может вернуть причину, которую прочитает модель.
- Списки разрешений для отдельных команд: открыть доступ к реестру только для одного запуска.
- Обновления в реальном времени:
--control-fdзаменяет сетевые списки во время выполнения команды. - Проверка разрешённого адреса: блокирует разрешённые имена, которые разрешаются в IP-адрес loopback или облачных метаданных.
- Причины запрета домена: сообщают агенту разрешённую альтернативу, например HTTPS-удалённый репозиторий git.
Как это сравнивается с другими песочницами для агентов?
| Функция | Anthropic sandbox-runtime | Песочница OpenAI Codex CLI | Docker Sandboxes | E2B |
|---|---|---|---|---|
| Изоляция | Примитивы ОС: Seatbelt, bubblewrap, учётная запись Windows + WFP | Примитивы ОС: Seatbelt, bubblewrap, встроенная песочница Windows | microVM для каждой песочницы | Firecracker microVM для каждого сеанса |
| Где работает | Локальный компьютер | Локальный компьютер | Локальный компьютер | Облако или BYOC (AWS, GCP) |
| Нужен контейнер или виртуальная машина | Нет | Нет | Да (microVM) | Да (управляемая microVM) |
| Использование вне собственного агента | Да, CLI + библиотека для любого процесса | Встроено в Codex | Да, CLI sbx для агентов программирования | Да, SDK для JS и Python |
| Сеть по умолчанию | Всё запрещено; список разрешений прокси | Отключена в workspace-write; переключатель конфигурации | Политика выбирается при первом запуске (например, deny-all, balanced) | Включена по умолчанию; её можно отключить |
| Список разрешённых доменов | Да, шаблоны + порты | Не раскрыт (документирован переключатель вкл./выкл.) | Да, шаблоны + порты | Да, allowOut с шаблонами (на основе SNI/Host) |
| Лицензия | Apache-2.0 | Apache-2.0 | Не раскрыта | Apache-2.0 (SDK) |
| Статус | Бета-версия исследовательского превью; Windows — альфа | Поставляется в Codex CLI | Готовый продукт | Готовый продукт |
Основные выводы
- srt изолирует любой процесс на уровне ОС, и контейнер не нужен.
- Seatbelt в macOS, bubblewrap в Linux, Windows — на стадии альфа-тестирования.
- Сеть по умолчанию запрещена; каждое соединение проходит через прокси со списком разрешений на стороне хоста.
- Anthropic сообщает о 84% меньшем количестве запросов разрешений Claude Code (внутренние данные).
- Широта списка разрешений — главный регулятор безопасности; широкие домены могут привести к утечке данных.
Ознакомьтесь с репозиторием GitHub, инженерной публикацией Anthropic и документацией по песочнице Claude Code. Все заслуги принадлежат исследователю этого проекта. Также подписывайтесь на нас в Twitter и не забудьте присоединиться к нашему сабреддиту по машинному обучению с более чем 150 тыс. участников и подписаться на нашу рассылку. Постойте! Вы есть в Telegram? теперь вы также можете присоединиться к нам в Telegram.
Хотите сотрудничать с нами для продвижения своего репозитория GitHub, страницы Hugging Face, релиза продукта, вебинара и т. д.? Свяжитесь с нами
Переведено автоматически с английского. Оригинал статьи — по ссылке ниже.