MarkTechPost출처 게시일

Anthropic의 sandbox-runtime 만나기: AI 에이전트를 위한 OS 수준 샌드박싱, 컨테이너 없이

이 글에서는 최근 주목받고 있는 오픈소스인 Anthropic의 sandbox-runtime (srt)에 대해 논의할 것입니다. 이는 Claude Code의 샌드박스 bash 도구를 뒷받침하는 OS 수준 샌드박스입니다.

이 글에서는 최근 주목받고 있는 오픈소스인 Anthropic의 sandbox-runtime (srt)에 대해 논의할 것입니다. 이는 Claude Code의 샌드박스 bash 도구를 뒷받침하는 OS 수준 샌드박스입니다. Anthropic sandbox-runtime은 프로세스가 접근할 수 있는 파일과 도달할 수 있는 호스트를 제한합니다. 컨테이너를 띄우지 않고 이를 수행합니다. 또한 Claude Code에 종속되지 않습니다. 여러분의 자체 에이전트, 로컬 MCP 서버 및 일반 명령줄 프로그램도 그 안에서 실행할 수 있습니다.

TL;DR

  • 크기: npm 패키지 @anthropic-ai/sandbox-runtime v0.0.81, 압축 해제 시 약 11.4 MB, Apache-2.0, Node.js 22.12+.
  • 실행 환경: macOS 또는 Linux 개발 머신 혹은 CI 박스라면 어디든. 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에서는 이러한 프록시가 샌드박스 안으로 bind-mount된 Unix 소켓 뒤에 위치합니다. macOS에서는 Seatbelt 프로파일이 하나의 localhost 포트만 허용합니다. 그런 다음 프록시가 도메인 허용 목록과 차단 목록을 적용합니다.

왜 파일시스템 격리와 네트워크 격리가 모두 필요한가요?

Anthropic 팀은 1가지 경계만으로는 다른 하나 없이는 실패한다고 주장합니다. 네트워크 격리가 없으면 프롬프트 인젝션을 당한 에이전트가 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 보고 내부 Claude Code 사용에서 샌드박싱이 권한 프롬프트를 84% 줄였다고 합니다. 이는 자체 보고 수치이며 외부 벤치마크가 아닙니다. 목표는 승인 피로입니다. 하루 종일 '승인'을 클릭하는 개발자들은 승인하는 내용을 읽지 않게 됩니다. 고정된 경계를 두면 에이전트가 그 안에서 자유롭게 작업하고 경계에서만 물어보게 됩니다.

Back</button> <button class="btn pri" id="fnext">다음 단계 </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">filesystem</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 &gt;&gt; .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>1회 설치</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 권한 확인 프롬프트(100 기준)</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">Anthropic의 내부 사용에서 프롬프트가 84% 감소했습니다(자체 보고, 2025년 10월 엔지니어링 게시물). 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">OS 기본 요소</td><td>OS 기본 요소</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>컨테이너 또는 VM</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>Sources: github.com/anthropics/sandbox-runtime · anthropic.com/engineering · v0.0.81</span><span class="mtp">Built by 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 alpha)가 전체 프로세스 트리에 파일 규칙을 적용합니다.',2,'act'], ['모든 트래픽이 프록시를 통과합니다','샌드박스에는 외부로 나가는 직접 경로가 없습니다. Linux에서는 네트워크 네임스페이스가 제거되며 Unix 소켓을 통해 프록시에 접근합니다.',3,'act'], ['허용된 호스트: 연결이 진행됩니다','allowedDomains에 있는 호스트는 루프백 또는 클라우드 메타데이터 IP로 확인되지 않는지 검사한 후 통과합니다.',4,'ok'], ['알 수 없는 호스트: 차단되거나 질의됨','거부되거나 목록에 없는 호스트는 거부되거나 ask 콜백이 결정합니다. 위반 사항은 에이전트가 읽을 수 있도록 기록됩니다.',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>Step '+(fi+1)+' of '+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,'Connection blocked by network allowlist','허용 목록에 일치하는 항목이 없습니다: 네트워크는 기본적으로 거부됩니다.']}, function(){return [0,'Connection blocked by network allowlist','example.com은 허용 목록에 없습니다.']}, function(){return on('d-npm')?[1,'packages installed (illustrative output)','*.npmjs.org가 허용 목록에 있으므로 레지스트리에 접근할 수 있습니다.']:[0,'npm ERR! network request to registry.npmjs.org failed\nConnection blocked by network allowlist','고전적인 트레이드오프: 너무 엄격하면 설치가 실패합니다.']}, function(){return on('f-env')?[0,'bash: .env: Operation not permitted','denyWrite가 allowWrite보다 우선하므로 .env는 프로젝트 내에서 보호됩니다.']:[1,'(written)','"."이 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,'&lt;')+'\n<span class="dim">샌드박스 내부에서 실행 중...</span>'; document.getElementById('why').textContent=''; setTimeout(function(){ t.innerHTML='<span class="p">$</span> '+b.textContent.replace(/</g,'&lt;')+'\n<span class="'+(r[0]?'ok':'no')+'">'+(r[0]?'✓ ':'✗ ')+r[1].replace(/</g,'&lt;')+'</span>'; document.getElementById('why').textContent=r[2];busy=false;post(); },650); })}); // platforms var P=['macOS는 실행마다 생성되는 Seatbelt 프로필과 함께 내장된 sandbox-exec 도구를 사용합니다. 프로필은 srt 프록시가 수신 대기하는 1개의 localhost 포트만 허용합니다. 위반 사항은 시스템 로그에서 실시간으로 읽을 수 있습니다.', 'Linux는 bubblewrap을 사용하며 네트워크 네임스페이스를 완전히 제거합니다. 프록시는 샌드박스에 바인드 마운트된 Unix 소켓을 통해 접근합니다. Ubuntu 24.04+는 사용자 네임스페이스를 위해 AppArmor 변경이 필요합니다.', 'Windows(alpha)는 전용 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> ">

진짜 트레이드오프: 엄격한 허용 목록 vs 작동하는 에이전트

코딩 에이전트는 파일 편집 이상의 작업을 합니다. 의존성을 설치하고, 문서를 가져오고, API를 호출합니다. 허용 목록을 너무 엄격하게 만들면 npm install 이 실패합니다. 너무 느슨하게 만들면 샌드박스가 거의 보호하지 못합니다. srt는 그 중간 지점을 위한 여러 조절 장치를 제공합니다:

  • 와일드카드와 포트: 같은 항목 *.npmjs.org 또는 api.example.com:443.
  • 콜백 요청(Ask callback): 어떤 규칙에도 해당하지 않는 호스트를 결정하며, 모델이 읽을 수 있는 사유를 반환할 수 있습니다.
  • 명령별 허용 목록(Per-command allow lists): 1회 호출에 한해 레지스트리를 엽니다.
  • 실시간 업데이트(Live updates): --control-fd 명령이 실행되는 동안 네트워크 목록을 교체합니다.
  • 확인된 주소 검사(Resolved-address check): 루프백 또는 클라우드 메타데이터 IP로 확인되는 허용된 이름을 차단합니다.
  • 거부된 도메인 사유(Denied-domain reasons): HTTPS git 원격과 같은 허용된 대안을 에이전트에게 알려줍니다..

다른 에이전트 샌드박스와는 어떻게 비교될까요?

기능Anthropic sandbox-runtimeOpenAI Codex CLI sandboxDocker SandboxesE2B
격리(Isolation)OS 기본 요소: Seatbelt, bubblewrap, Windows 계정 + WFPOS 기본 요소: Seatbelt, bubblewrap, 네이티브 Windows 샌드박스샌드박스당 microVM세션당 Firecracker microVM
실행 위치로컬 머신로컬 머신로컬 머신클라우드 또는 BYOC (AWS, GCP)
컨테이너 또는 VM 필요아니요아니요예 (microVM)예 (관리형 microVM)
자체 에이전트 외부에서 사용예, 모든 프로세스를 위한 CLI + 라이브러리Codex에 내장예, 코딩 에이전트용 sbx CLI예, JS 및 Python SDK
네트워크 기본값모두 거부; 프록시 허용 목록에서 꺼져 있음 workspace-write; 설정 토글첫 시작 시 정책 선택 (예: deny-all, balanced)기본적으로 켜짐; 비활성화 가능
도메인 허용 목록예, 와일드카드 + 포트공개되지 않음 (on/off 토글 문서화됨)예, 와일드카드 + 포트예, allowOut 와일드카드 지원 (SNI/Host 기반)
라이선스Apache-2.0Apache-2.0공개되지 않음Apache-2.0 (SDK)
상태베타 리서치 프리뷰; Windows 알파Codex CLI에 포함출시된 제품출시된 제품

핵심 요약

  • srt는 OS 수준에서 모든 프로세스를 샌드박스 처리하며, 컨테이너가 필요 없습니다.
  • macOS에서는 Seatbelt, Linux에서는 bubblewrap, Windows는 알파 단계입니다.
  • 네트워크는 기본적으로 거부되며, 모든 연결은 호스트 측 허용 목록 프록시를 통과합니다.
  • Anthropic은 Claude Code 권한 프롬프트가 84% 감소했다고 보고했습니다 (내부).
  • 허용 목록의 범위가 진짜 보안 다이얼입니다; 광범위한 도메인은 데이터를 유출할 수 있습니다.


확인해 보세요: GitHub 저장소, Anthropic 엔지니어링 포스트 , 그리고 Claude Code 샌드박싱 문서. 이 프로젝트의 연구자에게 모든 공이 돌아갑니다. 또한 저희를 Twitter 에서 팔로우하고, 저희의 150k+ML SubReddit 에 참여하고 저희 뉴스레터를 구독하는 것도 잊지 마세요. 잠깐! 텔레그램을 사용하시나요? 이제 텔레그램에서도 저희와 함께하실 수 있습니다.

GitHub 저장소 OR Hugging Face 페이지 OR 제품 출시 OR 웨비나 등을 홍보하기 위해 저희와 파트너십이 필요하신가요? 저희와 연락하세요

이 글 Anthropic의 sandbox-runtime을 소개합니다: AI 에이전트를 위한 OS 수준 샌드박싱, 컨테이너 없이 은 다음에서 처음 게시되었습니다: MarkTechPost.

원문 출처

MarkTechPost

내용 안내

원문 발행 및 권리는 출처에 있습니다.

기계 번역 · 원문을 참고하세요