
sandbox-runtime v0.0.67
임의의 프로세스에 대해 OS 수준에서 파일 시스템 및 네트워크 제한을 적용하는 가벼운 샌드박싱 도구로, 컨테이너가 필요하지 않습니다.
Anthropic Sandbox Runtime (srt)
컨테이너 없이 OS 수준에서 임의의 프로세스에 파일시스템 및 네트워크 제한을 적용하기 위한 경량 샌드박싱 도구입니다.
srt는 네이티브 OS 샌드박싱 프리미티브(macOS에서는 sandbox-exec, Linux에서는 bubblewrap)와 프록시 기반 네트워크 필터링을 사용합니다. 에이전트, 로컬 MCP 서버, bash 명령 및 임의의 프로세스의 동작을 샌드박싱하는 데 사용할 수 있습니다.
베타 리서치 프리뷰
Sandbox Runtime은 더 안전한 AI 에이전트를 구현하기 위해 Claude Code용으로 개발된 리서치 프리뷰입니다. 더 넓은 생태계가 보다 안전한 에이전트 시스템을 구축할 수 있도록 초기 오픈 소스 프리뷰로 공개되었습니다. 초기 리서치 프리뷰인 만큼 API와 구성 형식은 변경될 수 있습니다. AI 에이전트를 기본적으로 더 안전하게 만들기 위한 피드백과 기여를 환영합니다!
설치```bash
npm install -g @anthropic-ai/sandbox-runtime
## 기본 사용법```bash
# Network restrictions
$ srt "curl anthropic.com"
Running: curl anthropic.com
<html>...</html> # Request succeeds
$ srt "curl example.com"
Running: curl example.com
Connection blocked by network allowlist # Request blocked
# Filesystem restrictions
$ srt "cat README.md"
Running: cat README.md
# Anthropic Sandb... # Current directory access allowed
$ srt "cat ~/.ssh/id_rsa"
Running: cat ~/.ssh/id_rsa
cat: /Users/ollie/.ssh/id_rsa: Operation not permitted # Specific file blocked
개요
이 패키지는 CLI 도구와 라이브러리로 모두 사용할 수 있는 독립형 샌드박스 구현을 제공합니다. 일반적인 개발자 사용 사례에 맞춘 기본적으로 안전한(secure-by-default) 철학을 바탕으로 설계되었습니다. 프로세스는 최소한의 접근 권한으로 시작하며, 필요한 부분만 명시적으로 열어줍니다.
주요 기능:
- 네트워크 제한: HTTP/HTTPS 및 기타 프로토콜을 통해 접근할 수 있는 호스트/도메인 제어
- 파일시스템 제한: 읽기/쓰기가 가능한 파일/디렉터리 제어
- Unix 소켓 제한: 로컬 IPC 소켓에 대한 접근 제어
- 위반 모니터링: macOS에서 시스템의 샌드박스 위반 로그 저장소에 연결하여 실시간 경고 제공
사용 사례 예시: MCP 서버 샌드박싱
주요 사용 사례 중 하나는 Model Context Protocol(MCP) 서버를 샌드박싱하여 기능을 제한하는 것입니다. 예를 들어, 파일시스템 MCP 서버를 샌드박싱하려면:
샌드박싱 없이 (.mcp.json):```json
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem"]
}
}
}
**샌드박싱 사용** (`.mcp.json`):```json
{
"mcpServers": {
"filesystem": {
"command": "srt",
"args": ["npx", "-y", "@modelcontextprotocol/server-filesystem"]
}
}
}
그런 다음 ~/.srt-settings.json에서 제한 사항을 구성합니다:```json
{
"filesystem": {
"denyRead": [],
"allowWrite": ["."],
"denyWrite": ["~/sensitive-folder"]
},
"network": {
"allowedDomains": [],
"deniedDomains": []
}
}
이제 MCP 서버는 거부된 경로에 쓰기가 차단됩니다:```
> Write a file to ~/sensitive-folder
✗ Error: EPERM: operation not permitted, open '/Users/ollie/sensitive-folder/test.txt'
작동 방식
샌드박스는 OS 수준의 기본 요소를 사용하여 전체 프로세스 트리에 적용되는 제한을 시행합니다:
- macOS: 동적으로 생성된 Seatbelt 프로파일과 함께
sandbox-exec를 사용합니다 - Linux: 네트워크 네임스페이스 격리를 통한 컨테이너화를 위해 bubblewrap을 사용합니다
- Windows: 전용
srt-sandbox로컬 사용자 계정으로 샌드박스된 프로세스를 실행하며, 해당 계정의 SID를 키로 하는 Windows Filtering Platform 이그레스 펜스와 작업 트리에 대한 세션별 명시적 ACE를 사용합니다
0d1c612947c798aef48e6ab4beb7e8544da9d41a-4096x2305
이중 격리 모델
효과적인 샌드박싱을 위해서는 파일 시스템과 네트워크 격리가 모두 필요합니다. 파일 격리가 없으면 침해된 프로세스가 SSH 키나 기타 민감한 파일을 유출할 수 있습니다. 네트워크 격리가 없으면 프로세스가 샌드박스를 탈출하여 무제한 네트워크 접근 권한을 얻을 수 있습니다.
파일 시스템 격리는 읽기 및 쓰기 제한을 시행합니다:
- 읽기 (거부 후 허용 패턴): 기본적으로 읽기 접근은 모든 곳에서 허용됩니다. 넓은 영역(예:
/Users)을 거부한 다음 그 안의 특정 경로(예:.)를 다시 허용할 수 있습니다.allowRead는denyRead보다 우선합니다 — 쓰기와는 반대로, 쓰기에서는denyWrite가allowWrite보다 우선합니다.allowRead영역 내부에 있으면서 그보다 더 구체적인denyRead항목(예:allowRead: ["."]와 함께denyRead: ["**/.env"]또는["./secrets"])은 여전히 거부된 상태로 유지됩니다. - 쓰기 (허용 전용 패턴): 기본적으로 쓰기 접근은 모든 곳에서 거부됩니다. 경로(예:
.,/tmp)를 명시적으로 허용해야 합니다. 빈 허용 목록은 쓰기 접근이 없음을 의미합니다.
네트워크 격리 (허용 전용 패턴): 기본적으로 모든 네트워크 접근이 거부됩니다. 도메인을 명시적으로 허용해야 합니다. 빈 allowedDomains 목록은 네트워크 접근이 없음을 의미합니다. 네트워크 트래픽은 호스트에서 실행되는 프록시 서버를 통해 라우팅됩니다:
-
Linux: 요청은 Unix 도메인 소켓을 통해 파일 시스템을 경유하여 라우팅됩니다. 샌드박스된 프로세스의 네트워크 네임스페이스가 완전히 제거되므로, 모든 네트워크 트래픽은 호스트에서 실행되는 프록시(샌드박스에 바인드 마운트된 Unix 소켓에서 수신 대기)를 통해야 합니다
-
macOS: Seatbelt 프로파일은 특정 localhost 포트로의 통신만 허용합니다. 프록시가 이 포트에서 수신 대기하여 모든 네트워크 접근을 위한 제어된 채널을 만듭니다
-
Windows: 머신 전체의 WFP 필터 세트가 프록시 포트 범위로의 루프백을 제외하고
srt-sandbox계정에서 발생하는 모든 아웃바운드 연결을 차단합니다. 프록시가 해당 범위 내에서 수신 대기하여 모든 네트워크 접근을 위한 제어된 채널을 만듭니다
HTTP/HTTPS(HTTP 프록시 경유)와 기타 TCP 트래픽(SOCKS5 프록시 경유) 모두 이러한 프록시에 의해 중개되며, 프록시는 도메인 허용 목록과 거부 목록을 시행합니다.
Claude Code의 샌드박싱에 대한 자세한 내용은 다음을 참조하세요:
아키텍처```
src/ ├── index.ts # Library exports ├── cli.ts # CLI entrypoint (srt command) ├── utils/ # Shared utilities │ ├── debug.ts # Debug logging │ ├── settings.ts # Settings reader (permissions + sandbox config) │ ├── platform.ts # Platform detection │ └── exec.ts # Command execution utilities └── sandbox/ # Sandbox implementation ├── sandbox-manager.ts # Main sandbox manager ├── sandbox-schemas.ts # Zod schemas for validation ├── sandbox-violation-store.ts # Violation tracking ├── sandbox-utils.ts # Shared sandbox utilities ├── http-proxy.ts # HTTP/HTTPS proxy for network filtering ├── socks-proxy.ts # SOCKS5 proxy for network filtering ├── linux-sandbox-utils.ts # Linux bubblewrap sandboxing ├── macos-sandbox-utils.ts # macOS sandbox-exec sandboxing └── windows-sandbox-utils.ts # Windows srt-win sandboxing
## 사용법
### CLI 도구로 사용하기
`srt` 명령어(Anthropic Sandbox Runtime)는 모든 명령어를 보안 경계로 감쌉니다:```bash
# Run a command in the sandbox
srt echo "hello world"
# With debug logging
srt --debug curl https://example.com
# Specify custom settings file
srt --settings /path/to/srt-settings.json npm install
라이브러리로 사용하기```typescript
import { SandboxManager, type SandboxRuntimeConfig, } from '@anthropic-ai/sandbox-runtime' import { spawn } from 'child_process'
// Define your sandbox configuration const config: SandboxRuntimeConfig = { network: { allowedDomains: ['example.com', 'api.github.com'], deniedDomains: [], }, filesystem: { denyRead: ['~/.ssh'], allowWrite: ['.', '/tmp'], denyWrite: ['.env'], }, }
// Initialize the sandbox (starts proxy servers, etc.) await SandboxManager.initialize(config)
// Wrap a command with sandbox restrictions const sandboxedCommand = await SandboxManager.wrapWithSandbox( 'curl https://example.com', )
// Execute the sandboxed command const child = spawn(sandboxedCommand, { shell: true, stdio: 'inherit' })
// Handle exit and cleanup after child process completes
child.on('exit', async code => {
console.log(Command exited with code ${code})
// Cleanup when done (optional, happens automatically on process exit)
await SandboxManager.reset()
})
**위반 귀속(`commandId` / `commandText`).** 래핑된 명령이 실행되는 동안 관찰된 위반(seatbelt 로그 라인, seccomp 이벤트, 프록시 거부)은 귀속 키 아래에 저장되며, `annotateStderrWithSandboxFailures(key, stderr)` / `getViolationsForCommand(key)`는 동일한 키로 이를 조회합니다. 기본적으로 키는 래핑된 문자열 자체입니다. 대신 불투명한 호출별 `commandId`(예: 도구 사용 id)를 전달하여 그것으로 키를 지정하세요 — 권장 사항: 키는 처음 100자로 비교되므로, 접두사를 공유하는 긴 명령은 그렇지 않으면 교차 귀속될 수 있고, 동일한 텍스트를 재실행하면 이전 실행의 이벤트를 상속받게 됩니다. 만약 *실행*하는 문자열이 호출이 *나타내는* 명령과 다르다면(예: 조립된 `source <snapshot> && eval '<cmd>'`를 래핑하는 경우), `commandText: '<cmd>'`도 전달하세요: 이것이 `ignoreViolations` 명령 패턴이 대조하는 대상이며, 각 위반이 자신의 `command`로 보고하는 값입니다.```typescript
const wrapped = await SandboxManager.wrapWithSandbox(
assembledCommand, // what actually runs
undefined,
undefined,
undefined,
{ commandId: invocationId, commandText: rawCommand },
)
// ... run it ...
const annotated = SandboxManager.annotateStderrWithSandboxFailures(invocationId, stderr)
사용 가능한 내보내기```typescript
// Main sandbox manager export { SandboxManager } from '@anthropic-ai/sandbox-runtime'