Ch8. Sandbox 보안 런타임
Eve sandbox의 trust boundary, backend, network policy, credential brokering, workspace lifecycle을 운영 기준으로 정리한다.
핵심 요약
- Eve sandbox는 built-in shell/file 작업의 격리 경계이며 custom tool 실행 경계가 아닙니다.
- backend, network policy, workspace seed, credential brokering이 프로덕션 보안 posture를 좌우합니다.
- sandbox state는 session lifecycle과 맞물립니다. 재현성, 데이터 잔존, egress 제한을 함께 봐야 합니다.
Eve sandbox는 모델이 shell/file 작업을 수행하는 격리 환경입니다. 하지만 “sandbox가 있으니 안전하다”가 아니라 무엇이 sandbox에 들어가고, 어떤 network egress가 허용되고, 어떤 credential이 app runtime에 남는지가 중요합니다.
Trust boundary
| 항목 | App runtime | Sandbox |
|---|---|---|
| secrets/env | 있음 | 없음 |
custom tool execute | 실행 | 실행 안 됨 |
| built-in shell/file 효과 | proxy | /workspace에 발생 |
| filesystem | app code | isolated workspace |
| network | runtime 환경 | network policy |
모델이 bash를 호출해도 app runtime 파일시스템을 직접 만지지는 않습니다. 명령은 sandbox backend에서 실행됩니다. 반대로 custom tool은 app runtime에서 돌기 때문에 sandbox 격리의 보호를 받지 못합니다.
기본 도구
Sandbox를 대상으로 하는 built-in tools:
| Tool | 기능 |
|---|---|
bash | shell command 실행 |
read_file | line-numbered text read |
write_file | complete file write, read-before-write enforcement |
glob | file pattern search |
grep | regex content search |
엔터프라이즈에서는 이 도구들을 무조건 켜 두지 않습니다. 에이전트 목적에 맞춰 disable하거나 override합니다.
import { disableTool } from "eve/tools";
export default disableTool();Backend 선택
Eve는 여러 sandbox backend를 지원합니다.
| Backend | 실행 위치 | 기준 |
|---|---|---|
vercel() | Vercel Sandbox microVM | hosted production 기본 |
docker() | local Docker container | 로컬/셀프호스트에서 실제 binaries 필요 |
microsandbox() | local lightweight VM | Vercel Sandbox와 가까운 로컬 격리 |
justbash() | JS bash interpreter | 의존성 없는 fallback, 기능 제한 |
defaultBackend() | 환경에 따라 선택 | 빠른 시작, 명시성은 낮음 |
프로덕션에서는 backend를 암묵적으로 두지 말고 명시하세요. 특히 network policy와 resource option이 중요하다면 vercel()이나 defaultBackend({ vercel: ... }) 형태로 정책을 코드에 남깁니다.
defineSandbox 패턴
import { defineSandbox } from "eve/sandbox";
import { vercel } from "eve/sandbox/vercel";
export default defineSandbox({
backend: vercel({
runtime: "node24",
resources: { vcpus: 2 },
networkPolicy: "deny-all",
}),
revalidationKey: () => "bootstrap-v1",
async bootstrap({ use }) {
const sandbox = await use();
await sandbox.run({ command: "mkdir -p reports" });
},
async onSession({ use, ctx }) {
const sandbox = await use({ networkPolicy: "deny-all" });
const principal = ctx.session.auth.current?.principalId ?? "anonymous";
await sandbox.writeTextFile({
path: "SESSION_PRINCIPAL.txt",
content: `${principal}\n`,
});
},
});Bootstrap과 onSession을 구분한다
| Lifecycle | 실행 범위 | 넣을 것 | 넣으면 안 되는 것 |
|---|---|---|---|
bootstrap | template-scoped | 공통 package install, baseline repo clone | per-user secret, tenant data |
onSession | durable session-scoped | network policy, principal marker, per-session setup | 오래 걸리는 공통 setup 반복 |
bootstrap은 template를 재사용하기 위한 단계입니다. 외부 입력이 bootstrap 결과를 바꾼다면 revalidationKey를 설정하세요. onSession은 세션마다 한 번 실행되니 auth context 기반 설정을 넣기 좋습니다.
Workspace seed
agent/sandbox/workspace/** 아래 파일은 session bootstrap 시 /workspace/**에 복사됩니다.
agent/sandbox/
├── sandbox.ts
└── workspace/
├── schema.sql
└── scripts/run-report.sh주의:
workspace/skills/**는 금지됩니다. skills는agent/skills/가 담당합니다.- seed file에 secret을 넣지 않습니다.
- 고객 데이터 snapshot을 넣는다면 retention/deletion 정책을 둡니다.
- seed file 변경은 template cache/revalidation에 영향을 줍니다.
Network policy
기본 sandbox egress는 allow-all입니다. 민감한 데이터나 production data를 다루는 에이전트라면 반드시 조정하세요.
| 정책 | 의미 |
|---|---|
"allow-all" | 모든 egress 허용 |
"deny-all" | DNS 포함 egress 차단 |
| allow-list object | domain/subnet 기반 제한 |
예:
networkPolicy: {
allow: ["api.github.com", "*.vercel.com"],
subnets: { deny: ["10.0.0.0/8"] },
}Docker backend는 domain-level policy 지원이 제한적이고, just-bash는 network policy 동작 자체가 다릅니다. backend별 capability 차이를 운영 문서에 남겨 두세요.
Credential brokering
Vercel Sandbox와 microsandbox는 credential brokering을 지원합니다. 비밀값을 sandbox process에 직접 주지 않고, firewall/network layer에서 특정 host 요청에 header를 끼워 넣는 방식입니다.
사용 기준:
| 사용 | 판단 |
|---|---|
| private repo clone | brokering 적합 |
| arbitrary curl에 bearer 전달 | 위험, allow-list 필요 |
| 내부 API 호출 | 가능하면 custom tool/connection 선호 |
| 모델에게 token 문자열 전달 | 금지 |
Credential brokering은 편리하지만 마지막 수단으로 남겨 두세요. 비밀값이 필요한 작업은 가능한 한 app runtime tool로 감싸고 모델에는 요약 결과만 돌려주면, 나중에 감사하기 훨씬 쉽습니다.
Sandbox state와 session persistence
Sandbox는 session별로 /workspace 상태를 유지합니다. Vercel backend는 idle timeout 뒤에도 filesystem을 보존했다가 다음 메시지에서 재개합니다. Docker는 long-lived container로 유지되고, just-bash는 local cache를 씁니다.
운영 포인트:
- 세션별 sandbox id를 cache key로 쓴다.
- 장기 세션의 workspace size를 모니터링한다.
- 민감 artifact는 작업 종료 후 삭제하거나 retention job을 둔다.
- subagent sandbox는 declared subagent별로 분리될 수 있음을 이해한다.
Sandbox 보안 체크리스트
| 항목 | 기준 |
|---|---|
| backend | production backend 명시 |
| network | deny-all 또는 allow-list |
| secrets | workspace/seed file에 없음 |
| default tools | 목적에 맞게 disable/override |
| bootstrap | per-user data 없음, revalidationKey 있음 |
| onSession | auth 기반 정책 적용 |
| credential brokering | domain allow-list와 함께 사용 |
| eval | sandbox tool 호출과 network 제한 검증 |
Sandbox는 Eve의 가장 큰 장점이면서, 동시에 운영자가 가장 크게 착각하기 쉬운 영역입니다. “격리되어 있다”가 아니라 “어디까지 허용되어 있는가”를 기준으로 설계하세요.