규칙을 읽습니다
ai-jail은 내 ~/.ai-jail 파일을 신뢰합니다. 프로젝트 안의 .ai-jail 파일은 신뢰하지 않습니다. 이 파일은 샌드박스를 더 조일 수만 있고 열 수는 없습니다. 명령줄 플래그는 두 파일보다 우선합니다.
ai-jail은 시스템을 작고 닫힌 형태로 복제한 다음 그 안에 프로젝트를 넣고 에이전트를 시작합니다. 벽은 운영체제가 직접 제공하는 기능이라서 에이전트는 제 속도로 실행되고, 벽을 끌 수도 없습니다. 네트워크는 에이전트 자신의 API 호스트 말고는 닫힌 상태, 지정한 호스트 몇 개만 연 상태, 전부 연 상태 중 하나이고, 실행할 때마다 직접 고릅니다.
무엇이 실제로 강제되는지 알고 싶은 엔지니어를 위한 글입니다. 그 밖의 분께는 첫 문단과 첫 그림이면 충분합니다.
실행할 때마다 잠깐이면 끝나고, 그 뒤에 백그라운드에 남는 것은 없습니다.
↔ 옆으로 밀어 전체 다이어그램을 확인하세요
ai-jail은 내 ~/.ai-jail 파일을 신뢰합니다. 프로젝트 안의 .ai-jail 파일은 신뢰하지 않습니다. 이 파일은 샌드박스를 더 조일 수만 있고 열 수는 없습니다. 명령줄 플래그는 두 파일보다 우선합니다.
ai-jail은 에이전트가 생기기 전에 아래 계층을 모두 준비하고, 내가 가진 툴체인(mise, cargo, npm 등의 캐시)을 읽기 전용으로, 또는 감옥 전용 캐시로 매핑합니다. 설정 파일을 읽을 수 없거나 내용이 잘못되었으면 더 약한 규칙으로 시작하지 않고 그대로 멈춥니다.
에이전트와 에이전트가 띄우는 스크립트, 패키지, MCP 서버는 모두 같은 벽을 물려받습니다. 에이전트가 종료되면 ai-jail도 종료됩니다.
실행할 때마다 세 가지 네트워크 모드 중 하나를 고릅니다. 기본값이 가장 엄격해서, 필터링 프록시가 통과시키는 것 말고는 밖으로 나가는 경로가 없습니다. 프록시가 통과시키는 것은 두 플랫폼 모두에서 알려진 에이전트 자신의 API 호스트, 그리고 Linux에서 툴체인이 켜져 있을 때(기본값) 짧은 패키지 레지스트리 목록입니다. 나머지 둘은 일부러 넘기는 플래그입니다.
↔ 옆으로 밀어 전체 다이어그램을 확인하세요
기본값입니다. 샌드박스는 필터링 프록시 말고는 밖으로 나가는 경로가 없는 전용 네트워크 네임스페이스를 받습니다. 알려진 에이전트라면 프록시가 자기 API 호스트를 Linux와 macOS 모두에서 통과시켜, 플래그 없는 ai-jail claude가 그대로 동작합니다. Linux에서 툴체인이 켜져 있으면(기본값) 고정된 패키지 레지스트리 목록도 통과시켜 npm install과 cargo build가 동작합니다. macOS에서는 레지스트리가 닫혀 있습니다. --no-network를 주면 완전히 오프라인이 됩니다.
--allow-host HOST, 여러 번 쓸 수 있습니다. 네임스페이스는 닫힌 채로 두고, 안에 있는 작은 브리지가 트래픽을 바깥의 CONNECT 프록시로 전달합니다. 프록시는 나열한 호스트와 그 서브도메인에만 연결합니다. 이름은 바깥에서 한 번만 해석하고, 검사한 주소로만 연결합니다. ai-jail은 안에 http_proxy를 설정하고, 이를 무시하는 프로그램은 어디에도 닿지 못합니다.
--network. 네트워크 쪽 벽이 사라지고, 에이전트는 읽을 수 있는 것을 무엇이든 밖으로 보낼 수 있습니다.
| Linux | macOS | |
|---|---|---|
| 필터링 모드의 울타리 | 네트워크 네임스페이스 자체와 그 안의 브리지 | 프록시 포트로 나가는 연결만 허용하는 sandbox-exec 규칙 하나 |
| 샌드박스 안의 DNS | 실패합니다. 프록시가 바깥에서 이름을 해석합니다. | 시스템 리졸버에 울타리가 없어서 대역폭이 낮은 DNS 채널이 남습니다 |
ai-jail은 벽 하나가 혼자 버텨 주리라고 믿지 않습니다. Linux에서 에이전트는 커널이 강제하는 벽 다섯 겹 안에 있고, 여기에 들어가는 것과 나오는 것을 거르는 필터 두 개가 더해집니다.
↔ 옆으로 밀어 전체 다이어그램을 확인하세요
ai-sandbox)을 받습니다. 호스트 프로그램과 통하는 프로세스 간 채널이 없고, --allow-host나 --network로 열기 전에는 밖으로 나가는 경로가 없는 네트워크 네임스페이스에 있습니다. ai-jail이 죽으면 안에 있는 것도 전부 함께 죽습니다./usr 같은 시스템 디렉터리는 읽기 전용으로 마운트됩니다. 홈 디렉터리와 /tmp는 새로 만들어 메모리에 둡니다. 내가 가진 툴체인(mise, cargo, npm 캐시)은 이 새 홈 안에 읽기 전용으로, 또는 감옥 전용 캐시로 매핑됩니다.~/.ssh, ~/.aws, ~/.gnupg, ~/.docker, 브라우저 프로필은 절대 마운트하지 않는 내장 목록에 들어 있습니다. 하네스 자신의 상태 디렉터리, 예를 들어 Claude의 ~/.claude는 예외입니다. ai-jail은 에이전트가 로그인된 상태로 시작하도록 이것을 기본으로 읽기·쓰기 마운트하고, --no-agent-state를 주면 빼놓습니다. 프로젝트 바깥에 쓴 것은 세션이 끝나면 사라집니다.ptrace, mount, bpf, 커널 모듈, io_uring, 커널 키링, raw 소켓, 그리고 내 터미널에 키 입력을 밀어 넣을 수 있는 호출인 TIOCSTI입니다. 컴파일러와 런타임이 계속 동작하도록 일부러 차단 목록 방식을 택했습니다. Landlock과 seccomp이 적용되기 전에 시작되는 유일한 프로세스는 필터링된 네트워크 트래픽을 밖으로 나르는 작은 브리지이며, 이 프로세스만 제한 없이 남습니다.PATH, HOME, TERM, 로케일, 프록시, 인증서 설정입니다.ANTHROPIC_API_KEY로, 로그인과 함께 기본으로 복사됩니다. --no-agent-state로 막을 수 있습니다. 작업에 필요한 다른 변수는 --env에 이름을 지정해서 통과시킵니다.macOS에는 네임스페이스도 Landlock도 seccomp도 없습니다. ai-jail은 같은 정책을 Apple의 내장 샌드박스인 sandbox-exec용 프로파일로 바꿉니다. ai-jail 문서는 이것이 Linux의 격리와 동등하지 않다고 분명히 밝힙니다.
↔ 옆으로 밀어 전체 다이어그램을 확인하세요
| Linux | macOS | |
|---|---|---|
| 백엔드 | bubblewrap, 그 위에 Landlock, seccomp, 리소스 제한 | 실행할 때마다 생성한 프로파일을 쓰는 sandbox-exec. Apple이 deprecated로 지정했지만 커널 확장 없이 쓸 수 있는 더 나은 대안이 없습니다. |
| 홈 디렉터리 | 메모리에 새로 만든 홈. 실제 홈은 마운트되지 않습니다. | 프로파일은 전역 읽기 권한이 전혀 없는 상태에서 시작해 에이전트에 필요한 경로만 허용하므로 실제 홈은 닫혀 있습니다. |
/tmp | 전용이며 종료 시 폐기 | 마운트 네임스페이스가 없어서 호스트의 /tmp를 씁니다. TMPDIR은 실행할 때 만든 전용 폴더를 가리키고, 허용되는 임시 경로는 이것뿐입니다. |
| Copy-on-write 매핑 | --overlay-map으로 에이전트가 사본에 쓰게 합니다 | 읽기 전용 매핑으로 처리 |
| 네트워크 | 기본으로 닫힘. 알려진 에이전트 자신의 API 호스트와, 툴체인이 켜져 있을 때 허용되는 패키지 레지스트리 말고는 밖으로 나가는 경로가 없습니다. --allow-host나 --network로 더 열고, --forward-port는 호스트 루프백의 포트 하나를 중계하며, --no-network는 전부 닫습니다. --lockdown에서는 --network를 줘도 열린 네트워크가 항상 차단됩니다. | 같은 기본값, 같은 플래그를 쓰고 알려진 에이전트의 API 호스트도 같지만, --forward-port, 레지스트리, 툴체인 캐시 매핑은 Linux에만 있습니다. 락다운은 여기서도 열린 네트워크를 차단합니다. |
| 다른 프로그램 | 보이지 않음. 전용 프로세스 목록, 호스트 IPC 없음 | --macos-host-ipc를 넘기지 않으면 Mach, IOKit, 호스트 IPC를 거부 |
ai-jail은 보안 코드를 되도록 직접 작성하지 않습니다. 크기가 작고 주요 배포판이 모두 패키징하며 Flatpak이 매일 쓰고 있는 bubblewrap을 구동하고, 그 위에 커널 기능을 더합니다.
| 선택지 | 택하지 않은 이유 |
|---|---|
| Firejail | 기능은 충분하지만 setuid root 바이너리이고, 이 설계 때문에 나온 CVE가 여러 건입니다. bubblewrap은 root 없이 동작합니다. |
| bubblewrap을 Rust로 재작성 | 업스트림에서 수정을 받는 50 KB 정도의 의존성 하나를 없애려고 보안에 민감한 코드 500줄 이상을 혼자 유지보수하고 패치해야 합니다. |
| nsjail | 기능은 충분하지만 서버용으로 만들어졌고 protobuf 설정 파일로 구동하며, 패키징된 배포판이 적습니다. |
| systemd-nspawn | systemd가 필요해서 컨테이너 안이나 systemd가 없는 시스템에서는 동작하지 않습니다. |
도구 전체가 동기식 Rust 프로그램 하나입니다. async 런타임도, 데몬도, 컨테이너 이미지도 없습니다.
의존성은 ai-jail 저장소 버전 2.9.0 기준, 테스트는 버전 2.9.0 기준으로 센 숫자입니다.
ai-jail은 바이너리 하나입니다. 데몬도 root 권한도 필요 없습니다. 평소 실행하던 명령 앞에 단어 하나만 붙이면 됩니다.
brew tap akitaonrails/tap && brew install ai-jailai-jail claude