한계가 분명한 유용한 계층
ai-jail은 AI 코딩 에이전트를 키와 홈 디렉터리, 컴퓨터의 나머지 부분에서 떼어 놓습니다. 프로세스 샌드박스이므로 호스트와 커널을 공유합니다. 악의적인 코드를 다룰 때 일회용 가상 머신을 대신하지는 못합니다.
막으려고 만든 것
에이전트는 웹 페이지나 패키지, 저장소 안의 파일에 넘어가 나쁜 행동을 할 수 있습니다. 그때 에이전트가 찾으려 들지만 찾지 못하는 것들입니다.

닿을 수 없음
- 홈 디렉터리와 그 안의 자격 증명. 에이전트는 새로 만든 빈 홈을 받으므로 그 안에는
~/.ssh도~/.aws도 없습니다. - 셸에 있는 시크릿. 환경 변수는 작은 허용 목록에 있는 것만 남기므로 export한 토큰은 바깥에 남습니다.
- 네트워크. 꺼져 있어서 에이전트가 읽은 것을 어디로도 보낼 수 없습니다.
- 호스트 공유 메모리, 디스플레이 서버, 클립보드. 에이전트 출력은 터미널의 클립보드 시퀀스와 질의 시퀀스를 버리는 필터를 거칩니다.
- 터미널에 입력 밀어 넣기. Linux에서는 키 입력을 위조하는
TIOCSTI호출을 막고, macOS에서는 터미널 제어를 ai-jail이 그 실행용으로 만든 터미널 하나로 제한합니다. - 감옥 자체의 규칙. 저장소 안의
.ai-jail파일은 신뢰하지 않습니다. 샌드박스를 더 조일 수만 있고 열 수는 없습니다.
벽이 끝나는 곳
감옥과 내 시스템은 같은 커널 위에 서 있습니다. 그 커널이나 드라이버, 샌드박스 백엔드에 버그가 있으면 벽을 돌아가는 길이 생기고, ai-jail이 할 수 있는 일은 없습니다. 가상 머신은 자체 커널을 가져오기 때문에 더 강한 경계입니다.

여전히 위험한 것
- 커널과 드라이버 취약점. 샌드박스 안의 모든 프로세스는 컴퓨터의 나머지 부분과 같은 커널을 씁니다.
- 터미널 에뮬레이터 버그. 출력 필터를 끄는
--terminal-passthrough를 쓸 때 특히 그렇습니다. - 샌드박스 백엔드 자체의 결함. Linux에서는 bubblewrap, Landlock, seccomp이고 macOS에서는
sandbox-exec입니다. - 프로젝트 안의 시크릿. 저장소에 있는
.env파일은 마스킹하지 않으면 읽을 수 있습니다. 파일 마스킹 방법 보기. - 마스킹은 샌드박스가 시작될 때 존재하는 경로에만 적용됩니다. 세션 도중에 나중에 생긴 시크릿 파일은 숨겨지지 않습니다.
- 사이드 채널과 일부 유형의 프로세스 간 통신.
- macOS의
sandbox-exec는 Apple이 deprecated로 지정했고 Linux의 격리와 동등하지 않습니다. macOS에서 다른 점 보기.
벽을 여는 스위치
아래 항목은 모두 직접 켜기 전까지 꺼져 있고, 켜면 에이전트가 실제 접근 권한을 얻습니다. 설정 방법은 설정 페이지에 있습니다.
| 스위치 | 켜면 샌드박스 안의 모든 것이 할 수 있는 일 |
|---|---|
--network | 읽을 수 있는 것을 전부 어디로든 보냅니다. 트래픽에 제한이 없고 도메인별 필터도 없습니다. |
--docker | Docker 데몬을 통해 내 컴퓨터에서 root처럼 행동합니다. |
--x11 | 키 입력을 기록하고 다른 X11 창의 스크린샷을 찍습니다. |
--systemd-user | systemd 사용자 매니저에게 호스트에서 서비스를 실행해 달라고 요청합니다. |
--inherit-env | 시크릿을 포함한 셸 환경 전체를 읽습니다. |
--agent-state | Claude의 ~/.claude처럼 에이전트에 저장된 로그인을 씁니다. |
--audio | 켜져 있는 동안 오디오를 녹음하고 재생합니다. |
--no-private-home | 실제 홈 디렉터리를 봅니다. 범위가 넓은 예외이니 필요한 경로 하나만 매핑하는 편이 낫습니다. |
애매하면 시작을 거부합니다
요청한 것보다 약한 상태로 조용히 시작하는 샌드박스는 오류를 내고 멈추는 샌드박스보다 나쁩니다. 아래 경우에 ai-jail은 멈춥니다.
- 설정 파일이 있는데 내용이 잘못되었거나 읽을 수 없는 경우.
- 프로젝트
.ai-jail이 심볼릭 링크인 경우. 전역~/.ai-jail이 심볼릭 링크이면, 대상이 내 소유이고 다른 사람이 쓸 수 없으며 프로젝트 바깥에 있는 일반 파일일 때만 따라갑니다. --lockdown인데 커널 안에서 파일시스템 규칙을 적용하는 Landlock이 없거나, 일부만 지원되거나, 적용에 실패한 경우.--lockdown --no-landlock도 거부됩니다.--allow-tcp-port. 이 인터페이스는 UDP를 제한할 수 없어서, 호환성을 위해 플래그는 받되 실행은 실패합니다.BWRAP_BIN이 root가 아닌 누군가가 바꿔치기할 수 있었던 bubblewrap 바이너리를 가리키는 경우. 경고와 함께 무시되고, 신뢰할 수 있는 bubblewrap이 없으면 실행이 실패합니다.
프로젝트를 검증하는 방법
메인테이너 한 명이 프로젝트를 공개적으로 운영합니다. 무엇을 검증하고 무엇을 검증하지 못하는지 아래에 적었습니다.
- 19
- 샌드박스 탈출 통합 테스트.
/usr에 쓰기,~/.ssh읽기,ptrace와bpf호출을 시도하고 실패해야 통과합니다 - 720
- 버전 1.22.0 소스 트리에 있는 단위 테스트
- 0
- 실행 시 네트워크 요청 수. 업데이트 확인은
--update-check로 켜는 옵트인입니다
릴리스를 만드는 과정
- 릴리스 태그에 서명하고, CI가 저장소에 고정된 키 지문으로 태그를 하나씩 검증합니다.
- 모든 GitHub Action은 커밋 SHA로 고정되어 있고, 허용 목록에 있는 액션만 쓸 수 있습니다.
- 빌드에는 버전을 고정한 Rust 툴체인과
--locked의존성을 씁니다. - macOS 바이너리는 서명한 뒤 Apple의 공증을 받습니다.
- 압축 파일마다 SHA-256 체크섬이 함께 제공되고, 배포 작업에서 체크섬을 다시 확인합니다.
릴리스 문서가 밝힌, 아직 부족한 점
- 서명과 배포에 쓰는 시크릿이 아직 저장소 수준에 저장되어 있습니다. 릴리스 환경으로 옮겨야 합니다.
- 모든
v*태그에 서명을 강제하는 ruleset이 아직 없습니다. - 불변 릴리스(immutable releases)가 켜져 있지 않습니다.
- crates.io 배포에 아직 토큰을 씁니다. Trusted publishing을 도입할 계획입니다.
- 메인테이너가 한 명이라 변경 사항이나 릴리스를 검토할 두 번째 리뷰어가 없습니다.
취약점 신고
공개 이슈로 올리지 마세요. GitHub의 비공개 취약점 신고 기능을 쓰고, 재현 절차와 영향받는 버전을 적어 주세요. 수정을 조율할 시간도 필요합니다.
자주 묻는 질문
에이전트가 탈출할 수 있나요?
네트워크를 켜고 실행해도 안전한가요?
감사를 받았나요?
에이전트를 철창 안에 넣으세요
ai-jail은 바이너리 하나입니다. 데몬도 root 권한도 필요 없습니다. 평소 실행하던 명령 앞에 단어 하나만 붙이면 됩니다.
brew tap akitaonrails/tap && brew install ai-jailai-jail claude