클로드 코드 샌드박스: OS 레벨 격리로 안전하게 코딩하기

클로드 코드 샌드박스: OS 레벨 격리로 안전하게 코딩하기

클로드 코드를 써보셨다면 “이 명령어를 실행해도 될까요?”라는 팝업이 익숙하실 겁니다. 처음엔 안전장치니까 반갑지만 반복되면 점점 피로해지죠. 결국 내용을 대충 훑고 승인 버튼을 누르게 되는데 이러면 오히려 보안에 취약해집니다. Claude Code의 샌드박스는 이 문제를 해결합니다. 명령어를 일일이 검사하는 대신 OS 레벨에서 실행 환경 자체를 격리해서 안전한 경계 안에서는 자유롭게, 경계 밖으로는 절대 못 나가게 만드는 거죠.

왜 샌드박스가 필요한가

클로드 코드 권한 설정에서 다뤘던 권한 시스템은 “이 도구를 써도 되는가?”를 판단합니다. 유용하긴 한데 Bash 명령어 하나하나에 대해 승인을 요청하다 보면 개발 흐름이 끊기고 사용자는 승인 피로(approval fatigue)에 빠지게 돼요.

샌드박스는 접근 방식이 다릅니다. “이 경계 안에서는 마음껏 해”라고 울타리를 쳐놓는 겁니다. 울타리 안에서 실행되는 명령어는 승인 없이 자동 실행되고 울타리 밖으로 나가려는 시도는 OS가 차단합니다. 승인 팝업은 줄어들고 보안은 오히려 강화되는 셈이죠.

“그러면 --dangerously-skip-permissions로 팝업을 다 끄면 되지 않나?”라고 생각할 수 있는데 이건 울타리를 아예 치워버리는 겁니다. Claude가 파일을 삭제하든 curl로 외부에 데이터를 보내든 아무 제한이 없어요. 샌드박스는 반대로 울타리를 세우는 방식이라 팝업은 줄이면서 보안은 유지됩니다. 장시간 돌아가는 작업에서 --dangerously-skip-permissions를 꼭 써야 한다면 샌드박스를 함께 켜서 OS 레벨 격리라도 유지하는 편이 안전해요.

여기서 중요한 점이 있습니다. 파일 시스템 격리와 네트워크 격리는 반드시 함께 적용해야 해요. 네트워크 격리 없이 파일 시스템만 보호하면 악의적인 코드가 SSH 키 같은 민감한 파일을 외부로 빼돌릴 수 있습니다. 반대로 파일 시스템 격리 없이 네트워크만 차단하면 시스템 파일을 조작해서 네트워크 접근 권한을 확보할 수 있거든요.

파일 시스템 격리

샌드박스가 파일 시스템을 격리하는 방식은 단순합니다.

현재 작업 디렉토리와 하위 디렉토리에는 읽기/쓰기가 가능합니다. 그 외 경로는 기본적으로 읽기만 허용되고 ~/.bashrc/bin/ 같은 민감한 시스템 파일은 아예 접근이 차단돼요. 프롬프트 인젝션 공격으로 Claude의 판단이 흐려지더라도 샌드박스가 시스템 파일 수정을 물리적으로 막아주니까 걱정할 필요가 없습니다.

kubectl, terraform, npm 같은 도구가 내부적으로 파일을 쓰려 해도 동일한 경계를 따릅니다. Bash 명령어의 모든 자식 프로세스에 OS 레벨로 적용되기 때문이에요.

프로젝트 디렉토리 바깥에 쓰기 권한이 필요한 경우에는 sandbox.filesystem.allowWrite로 특정 경로를 추가로 열어줄 수 있습니다. 예를 들어 kubectl~/.kube에 접근해야 하거나 빌드 산출물을 /tmp/build에 저장해야 하는 상황이죠.

{
  "sandbox": {
    "filesystem": {
      "allowWrite": ["~/.kube", "//tmp/build"],
      "denyRead": ["~/.aws/credentials"]
    }
  }
}

반대로 filesystem.denyWritefilesystem.denyRead로 특정 경로의 접근을 직접 차단할 수도 있어요. 이 설정은 클로드 코드 권한 설정Edit/Read deny 규칙과 합쳐져서 최종 샌드박스 구성에 반영됩니다.

경로를 지정할 때 접두사에 따라 해석 방식이 달라지니 주의하세요. //는 파일 시스템 루트 기준 절대 경로입니다(//tmp/build/tmp/build). ~/는 홈 디렉토리 기준이고(~/.kube$HOME/.kube), /는 설정 파일이 위치한 디렉토리 기준이에요(/build$SETTINGS_DIR/build). ./이나 접두사 없는 경로는 샌드박스 런타임이 상대 경로로 해석합니다.

여러 설정 범위(managed, user, project, local)에서 allowWritedenyWrite를 정의하면 배열이 병합됩니다. managed 설정에서 //opt/company-tools를 허용하고 개인 설정에서 ~/.kube를 추가하면 두 경로 모두 최종 샌드박스에 포함돼요. 덮어쓰기가 아니라 합치기라서 각 범위가 독립적으로 경로를 확장할 수 있습니다.

네트워크 격리

네트워크 격리는 샌드박스 외부에서 동작하는 프록시 서버를 통해 구현됩니다. 모든 네트워크 요청이 이 프록시를 거치기 때문에 허용된 도메인만 접근할 수 있죠.

허용되지 않은 도메인으로 요청을 보내면 OS 레벨에서 차단되고 사용자에게 알림이 갑니다. 이때 요청을 거부하거나 한 번만 허용하거나 설정을 업데이트해서 계속 허용할 수 있어요.

조직 차원에서 더 엄격한 통제가 필요하다면 managed 설정의 network.allowManagedDomainsOnlytrue로 설정할 수 있습니다. 이 경우 사용자나 프로젝트 설정의 도메인은 무시되고 관리자가 지정한 도메인만 허용돼요. 허용 목록에 없는 도메인은 사용자에게 묻지도 않고 자동으로 차단됩니다.

npm install이 내부적으로 보내는 HTTP 요청도 빌드 스크립트가 호출하는 API도 모두 같은 도메인 규칙을 따릅니다. 자식 프로세스까지 전부 적용되니까 빠져나갈 틈이 없어요.

OS 레벨 강제 적용

샌드박스가 단순한 소프트웨어 제한이 아니라 OS 보안 기능을 활용한다는 점이 핵심입니다.

macOS에서는 Apple이 만든 Seatbelt 프레임워크를 사용합니다. 별도 설치 없이 바로 쓸 수 있어요.

Linux와 WSL2에서는 bubblewrap을 사용합니다. Ubuntu/Debian이라면 다음 명령으로 설치합니다.

sudo apt-get install bubblewrap socat

Fedora 사용자는 dnf로 설치하면 됩니다.

sudo dnf install bubblewrap socat

WSL1은 bubblewrap에 필요한 커널 기능이 없어서 지원되지 않습니다. WSL1을 쓰고 있다면 WSL2로 업그레이드해야 해요.

OS 레벨 보안 프리미티브를 쓰기 때문에 Claude가 실행하는 명령어의 모든 자식 프로세스도 같은 보안 경계를 상속받습니다. 애플리케이션 레벨에서 우회할 방법이 사실상 없어요.

샌드박스 활성화

Claude Code에서 /sandbox 명령을 실행하면 샌드박스 설정 메뉴가 열립니다.

❯ /sandbox

─────────────────────────────────────────────────
  Sandbox:  Mode   Overrides   Config


  Configure Mode:

  ❯ 1. Sandbox BashTool, with auto-allow
    2. Sandbox BashTool, with regular permissions
    3. No Sandbox (current)

  Auto-allow mode: Commands will try to run in the sandbox automatically, and attempts to run outside of the sandbox fallback to regular permissions. Explicit ask/deny rules are always respected.

  Learn more: code.claude.com/docs/en/sandboxing

필요한 패키지가 설치되지 않았으면 플랫폼별 설치 안내가 표시돼요.

샌드박스에는 두 가지 모드가 있습니다.

자동 허용 모드(Auto-allow)에서는 샌드박스 안에서 실행 가능한 Bash 명령어가 권한 확인 없이 자동으로 실행됩니다. 샌드박스 안에서 실행할 수 없는 명령어(허용되지 않은 도메인에 접근하는 경우 등)는 사용자에게 허용/거부를 묻는 권한 확인 팝업이 평소처럼 뜹니다. 즉, 샌드박스가 보호할 수 있는 범위 안에서만 자동 실행되고, 그 밖의 작업은 사용자가 직접 판단하는 거예요.

일반 권한 모드(Regular permissions)에서는 샌드박스 안에서 실행되더라도 모든 Bash 명령어에 대해 허용/거부 팝업이 뜹니다. 보안을 최우선으로 하는 환경에 적합하지만 팝업이 더 자주 뜨죠.

두 모드 모두 파일 시스템과 네트워크 격리는 동일하게 적용됩니다. 차이는 승인 과정에만 있어요.

자동 허용 모드는 권한 모드 설정과 독립적으로 동작합니다. “accept edits” 모드가 아니더라도 샌드박스 안의 Bash 명령은 자동 실행되니까 기억해 두세요.

설정 방법

클로드 코드 설정 가이드에서 다룬 settings.json으로 샌드박스 동작을 세밀하게 제어할 수 있습니다.

{
  "sandbox": {
    "enabled": true,
    "autoAllowBashIfSandboxed": true,
    "excludedCommands": ["docker"],
    "filesystem": {
      "allowWrite": ["//tmp/build", "~/.kube"],
      "denyRead": ["~/.aws/credentials"]
    },
    "network": {
      "allowedDomains": ["github.com", "*.npmjs.org"],
      "allowLocalBinding": true
    }
  }
}

enabled는 샌드박스 활성화 여부입니다.

autoAllowBashIfSandboxedtrue로 설정하면 샌드박스 안에서 실행되는 Bash 명령은 권한 확인 없이 자동 허용됩니다. 샌드박스가 시스템을 보호해주니까 팝업 피로를 줄이면서도 안전하죠.

excludedCommands에 넣은 명령어는 샌드박스를 거치지 않고 실행됩니다. docker는 샌드박스와 호환되지 않아서 여기에 넣어두는 것이 좋고 watchman을 쓰는 jestjest --no-watchman으로 실행하거나 제외 목록에 추가해야 합니다.

filesystem 하위 설정으로 파일 시스템 접근을 세밀하게 조정합니다. allowWrite로 프로젝트 디렉토리 외부의 쓰기 경로를 추가하고 denyRead로 민감한 파일의 읽기를 차단할 수 있어요. 특정 도구가 프로젝트 밖에 파일을 써야 할 때 excludedCommands로 샌드박스를 통째로 빼는 것보다 allowWrite로 필요한 경로만 여는 편이 낫습니다.

network.allowedDomains는 Bash 명령어가 접근할 수 있는 도메인 목록입니다. 와일드카드(*.npmjs.org)를 지원해서 하위 도메인을 한 번에 허용할 수 있어요.

network.allowLocalBindingtrue로 하면 로컬 포트 바인딩이 허용됩니다(macOS만 해당). 개발 서버를 띄울 때 필요하죠.

샌드박스에는 탈출구도 마련되어 있습니다. 명령어가 샌드박스 제한 때문에 실패하면 Claude가 실패 원인을 분석한 뒤 dangerouslyDisableSandbox 파라미터로 샌드박스 밖에서 재시도할 수 있어요. 이때 사용자에게 허용/거부 팝업이 뜨기 때문에 승인 없이 실행되지는 않습니다. 보안이 중요한 환경이라면 "allowUnsandboxedCommands": false로 이 탈출구를 완전히 닫을 수 있어요. 이 경우 모든 명령어는 반드시 샌드박스 안에서 실행되거나 excludedCommands에 명시되어야 합니다.

권한과 샌드박스의 관계

클로드 코드 권한 설정에서 다룬 권한 시스템과 샌드박스는 서로 다른 계층에서 보안을 담당합니다.

권한(Permissions)은 Claude Code가 어떤 도구를 쓸 수 있는지 제어합니다. Bash, Read, Edit, WebFetch, MCP 등 모든 내장 도구에 적용되고 도구가 실행되기 전에 평가돼요.

샌드박스(Sandbox)는 Bash 명령어와 그 자식 프로세스가 접근할 수 있는 파일과 네트워크를 OS 레벨에서 격리합니다. Bash 명령에만 적용되지만 프롬프트 인젝션으로 권한 시스템이 우회되더라도 추가 방어선 역할을 해요.

이 둘을 함께 쓰면 다층 방어(defense-in-depth)가 완성됩니다.

{
  "permissions": {
    "deny": ["Bash(curl *)", "Bash(wget *)"],
    "allow": ["Bash(npm run *)"]
  },
  "sandbox": {
    "enabled": true,
    "autoAllowBashIfSandboxed": true,
    "network": {
      "allowedDomains": ["github.com", "*.npmjs.org"]
    }
  }
}

권한 시스템의 deny 규칙이 curlwget을 차단하고 샌드박스의 도메인 제한이 그 외 네트워크 접근도 통제합니다. npm run *은 allow 규칙으로 허용하되 샌드박스가 실행 범위를 제한하니까 안전하게 자동 실행할 수 있죠. Read/Edit의 deny 규칙이나 WebFetch의 allow/deny 규칙도 샌드박스 구성에 함께 병합되기 때문에 두 계층이 자연스럽게 맞물립니다.

프롬프트 인젝션 방어

샌드박스의 진가는 프롬프트 인젝션 공격을 받았을 때 드러납니다. 공격자가 악의적인 지시를 Claude에게 주입하더라도 샌드박스가 실제 피해를 막아주거든요.

파일 시스템 쪽에서는 ~/.bashrc 같은 설정 파일을 수정할 수 없고 /bin/ 아래의 시스템 바이너리도 건드릴 수 없습니다. 클로드 코드 권한 설정에서 deny로 설정한 파일도 당연히 못 읽어요.

네트워크 쪽에서는 허용 목록에 없는 서버로 데이터를 보낼 수 없습니다. 악성 스크립트 다운로드나 승인되지 않은 API 호출도 차단되죠.

악성 NPM 패키지, 취약한 빌드 스크립트, 소셜 엔지니어링 공격 등 여러 위협에 대해 피해 범위를 줄일 수 있어요.

보안 한계

샌드박스가 만능은 아닙니다. 몇 가지 한계를 알아두세요.

우선 네트워크 필터링은 도메인 단위로 동작해서 트래픽 내용 자체를 검사하지는 않아요. github.com처럼 범용 도메인을 허용하면 데이터 유출 경로가 될 수 있고 도메인 프론팅 기법으로 필터링을 우회할 가능성도 있으니 신뢰할 수 있는 도메인만 넣으세요.

allowUnixSockets도 주의가 필요합니다. /var/run/docker.sock 같은 소켓에 접근을 허용하면 Docker를 통해 호스트 시스템까지 뚫릴 수 있거든요.

파일 시스템 쪽은 쓰기 권한 범위를 좁게 잡는 게 핵심이에요. $PATH 디렉토리나 .bashrc, .zshrc 같은 셸 설정 파일에 쓰기를 열어두면 권한 상승(privilege escalation) 공격에 노출됩니다.

Linux에서 Docker 컨테이너처럼 권한이 제한된 환경이라면 enableWeakerNestedSandbox 옵션을 쓸 수 있는데 이름 그대로 보안이 약해지니까 추가 격리가 보장될 때만 켜세요.

macOS에서 커스텀 프록시와 MITM CA를 쓸 때 gh, gcloud, terraform 같은 Go 기반 도구가 TLS 인증서 검증에 실패하는 경우가 있습니다. enableWeakerNetworkIsolationtrue로 설정하면 시스템 TLS 신뢰 서비스(com.apple.trustd.agent) 접근이 열리지만 데이터 유출 경로도 함께 열릴 수 있어요. 커스텀 프록시 환경에서만 쓰는 게 안전합니다.

성능 오버헤드는 거의 없지만 일부 파일 시스템 작업이 미세하게 느려질 수 있어요. 특정 도구는 설정 조정이나 excludedCommands 처리가 필요할 수도 있고요. 현재 macOS, Linux, WSL2를 지원하며 네이티브 Windows 지원은 계획 중입니다.

커스텀 프록시 설정

조직 차원의 네트워크 보안이 필요하다면 커스텀 프록시를 설정할 수 있습니다. HTTPS 트래픽을 복호화해서 검사하거나 커스텀 필터링 규칙을 적용할 수 있고 모든 네트워크 요청을 로깅하거나 기존 보안 인프라와 통합하는 것도 가능해요.

{
  "sandbox": {
    "network": {
      "httpProxyPort": 8080,
      "socksProxyPort": 8081
    }
  }
}

오픈 소스

샌드박스 런타임은 오픈 소스 npm 패키지로 공개되어 있어서 자체 프로젝트에서도 활용할 수 있습니다. MCP 서버를 샌드박스 안에서 실행하고 싶다면 이렇게 쓰면 돼요.

npx @anthropic-ai/sandbox-runtime <실행할-명령어>

AI 에이전트를 개발하는 분이라면 구현 세부 사항과 소스 코드를 GitHub 저장소에서 확인해보세요.

실전 팁

샌드박스는 가능하면 항상 켜두는 게 좋습니다. 잃는 건 미미한 성능 오버헤드와 일부 도구의 설정 조정 정도인데 얻는 건 OS 레벨 파일/네트워크 격리와 승인 팝업 감소예요. settings.json"sandbox": { "enabled": true, "autoAllowBashIfSandboxed": true }를 넣어두면 새 세션마다 자동으로 켜집니다.

샌드박스를 켜도 실행 환경은 바뀌지 않습니다. Docker 컨테이너처럼 격리된 별도 환경을 만드는 게 아니라 현재 작업 디렉토리에서 그대로 실행되면서 OS가 접근 범위만 제한하는 방식이에요. 그래서 설정 변경 없이 바로 쓸 수 있고 기존 개발 환경과 충돌할 일도 없습니다.

세션 도중에 /sandbox 명령을 다시 실행하면 모드를 전환하거나 끌 수도 있어요. 자동 허용 모드와 일반 권한 모드 사이를 오가거나 아예 끄는 것도 자유롭습니다. 다만 CLI 플래그(claude --sandbox 같은 것)는 없으니 settings.json이나 /sandbox 명령으로만 제어해야 해요.

마치며

Claude Code의 샌드박스는 “일일이 물어보고 허가받는” 보안에서 “울타리 안에서 자유롭게 뛰노는” 보안으로 전환해줍니다. OS 레벨 격리로 파일 시스템과 네트워크를 동시에 보호하니까 프롬프트 인젝션 같은 공격이 들어와도 피해를 막을 수 있어요.

처음 쓸 때는 /sandbox 명령으로 활성화한 뒤 자동 허용 모드를 켜는 것만으로도 체감이 확 달라집니다. 그 뒤에 도메인 허용 목록과 제외 명령어를 프로젝트에 맞게 조정하면 돼요.

클로드 코드 권한 설정으로 도구별 접근을 제어하고 샌드박스로 Bash 실행 환경을 격리한 뒤 클로드 코드 Hooks로 커스텀 검증 로직까지 더하면 안전하면서도 흐름이 끊기지 않는 AI 코딩 환경을 만들 수 있습니다. 이런 설정을 팀 전체에 배포하고 싶다면 플러그인으로 묶어서 마켓플레이스에 올리는 방법도 살펴보세요. 샌드박스 런타임의 공식 문서도 참고해보세요.

This work is licensed under CC BY 4.0 CC BY

개발자를 위한 뉴스레터

달레가 정리한 AI 개발 트렌드와 직접 만든 콘텐츠를 전해드립니다.

Discord