코덱스(Codex) 샌드박스 오류, 파일 쓰기와 인터넷 설정 점검법
Codex 샌드박스 오류를 코덱스 CLI로 재현해 보니 읽기 전용에서는 파일이 만들어지지 않았고, 작업 폴더 쓰기에서는 파일이 만들어졌지만 curl 접속은 실패했습니다. 실패 원인은 확인하지 못했습니다. 모드를 바꾸는 법과 네트워크를 여는 설정, 승인 규칙을 함께 정리했습니다.
Finn · · 수정

코덱스(Codex) CLI에 "hello.txt 파일을 만들어 달라"고 똑같이 요청해도 결과는 모드마다 다릅니다. 읽기 전용 모드에서는 8.7초 뒤 "파일을 만들 수 없다"는 답만 돌아오고, 작업 폴더 쓰기 모드에서는 10.9초 만에 파일이 생기죠. 그런데 같은 작업 폴더 쓰기 모드에서도 curl로 인터넷에 접속하게 하면 명령이 종료 코드 6으로 끝납니다. 'Codex 샌드박스 오류'로 검색해 왔다면, 이 세 가지 결과를 기준으로 원인과 해결 순서를 확인해 보세요.
모드별로 실행하면 어떤 결과가 나올까요?
새 임시 폴더에서 codex exec로 같은 요청을 모드만 바꿔 한 번씩 실행했습니다. 모드는 -s 옵션으로 지정했고, 읽기 전용 단계는 이렇게 실행합니다.
$ codex exec --ephemeral --skip-git-repo-check --ignore-user-config -m gpt-6.1-sol -s read-only "hello.txt 파일을 만들고 안녕이라고 한 줄 써 주세요" 2>&1 | tail -8; ls| 단계 | 모드 | 걸린 시간 | 결과 |
|---|---|---|---|
| 파일 만들기 | read-only | 8.7초 | 파일을 만들지 않고 직접 실행할 printf 명령만 안내 |
| 같은 요청 | workspace-write | 10.9초 | hello.txt 생성, cat으로 "안녕" 확인 |
| 인터넷 접속 | workspace-write | 7.2초 | curl -sI https://example.com이 0ms 만에 종료 코드 6으로 끝남 |
세 단계 모두 기록된 종료 코드는 0이었습니다. 다만 측정한 명령은 | tail -8, ; ls, ; cat hello.txt처럼 끝에 다른 명령을 이은 형태입니다. 그래서 이 0은 파이프 끝에 있는 tail·ls·cat의 값이고, codex 자체가 성공했는지 실패했는지를 뜻하지 않습니다. 기록된 셸 명령 전체는 0으로 끝났지만, 이 명령 구성으로는 codex 자체의 종료 코드를 확인할 수 없습니다. 그래서 각 단계의 결과는 출력과 만들어진 파일로 확인했습니다. 게다가 네 번째 단계에서 에이전트는 "출력이 없어 첫 줄이 없습니다"라고만 답했고, 네트워크가 막혔다는 말은 하지 않았습니다. 스크립트로 코덱스를 돌리고 있다면 종료 코드만 보지 말고 만들어진 파일과 출력을 따로 확인하는 편이 안전합니다.

그렇다면 이렇게 막혔을 때는 무엇부터 바꿔야 할까요? 다음 절에서 순서대로 정리합니다.
함께 읽을 글
막혔을 때 따라 할 순서
- 지금 모드부터 확인합니다. CLI에서는
/permissions를 입력하면 권한 선택 화면이 열리고, 데스크톱 앱과 IDE 확장에서는 입력창 아래 권한 컨트롤을 쓰면 됩니다. - 파일 편집이 필요하면 작업 폴더 쓰기로 바꿉니다. 한 번만 바꿀 때는 위 측정처럼
-s workspace-write를 붙이세요. 공식 문서가 위험이 낮은 로컬 자동화 조합으로 소개하는 플래그는--sandbox workspace-write --ask-for-approval on-request입니다. - 매번 같은 동작을 원하면
config.toml에 기본값을 둡니다.sandbox_mode와approval_policy가 그 키입니다. - 작업 폴더 밖도 써야 하면 샌드박스를 끄지 말고
sandbox_workspace_write.writable_roots로 쓸 수 있는 폴더를 늘립니다. - 인터넷이 필요하면 아래 네트워크 절의 설정을 켭니다.
- 특정 명령만 샌드박스 밖에서 돌려야 하면 접근 범위를 넓히는 대신 규칙(rules) 파일을 씁니다.
- Linux나 WSL2라면 먼저
bubblewrap을 설치합니다. 맥은 내장된 Seatbelt로 바로 동작합니다.
sudo apt install bubblewrapUbuntu 24.04에서는 설치 후에도 사용자 네임스페이스를 만들 수 없다는 경고가 남을 수 있습니다. 이럴 때는 Sandbox 문서에 있는 AppArmor 프로필 적용 절차를 따라 하세요.
샌드박스 모드마다 허용하는 범위
공식 문서가 꼽는 대표 모드는 세 가지입니다. read-only는 파일을 살펴볼 수만 있고, 승인 없이는 파일을 고치거나 명령을 실행하지 못합니다. workspace-write는 작업 폴더 안에서 편집하고 일상적인 로컬 명령을 돌릴 수 있는 기본 모드예요. danger-full-access는 샌드박스 제한 없이 실행됩니다.

샌드박스는 내장 파일 작업에만 걸리는 게 아닙니다. 에이전트가 git, 패키지 매니저, 테스트 도구를 실행해도 같은 경계가 그대로 이어집니다. 그래서 npm install처럼 네트워크가 필요한 명령도 같은 이유로 막힐 수 있죠.
코덱스 승인 모드는 어떻게 다를까요?
샌드박스는 무엇을 할 수 있는지를 정하고, 승인 정책(approval policy)은 언제 멈춰서 물을지를 정합니다. 흔히 쓰는 승인 정책은 두 가지입니다.
on-request: 평소에는 샌드박스 안에서 일하다가 경계를 넘어야 할 때만 묻습니다.never: 승인 요청 없이 진행합니다.
예를 들어 Auto 조합(workspace-write + on-request)에서는 작업 폴더 밖 파일을 고치거나 네트워크가 필요한 명령을 실행할 때 승인을 요청합니다. 승인을 요청받는 사람은 approvals_reviewer로 정하는데, 기본값 user는 사용자에게 묻고 auto_review는 조건에 맞는 요청을 검토 에이전트에게 넘깁니다.
승인을 계속 물을 때는 어떻게 할까요?
같은 명령에 매번 승인 창이 뜬다면 규칙 파일로 그 명령만 예외를 둘 수 있습니다. 규칙은 아직 실험 기능이라 바뀔 수 있다는 점을 기억해 두세요. 순서는 Rules 문서 그대로입니다.
~/.codex/rules/default.rules처럼 설정 계층 옆rules/폴더에.rules파일을 만듭니다.- 규칙을 추가합니다. 아래 예시는
gh pr view를 샌드박스 밖에서 실행하기 전에 묻게 합니다. - 코덱스를 다시 시작합니다.
# Prompt before running commands with the prefix `gh pr view` outside the sandbox.
prefix_rule(
# The prefix to match.
pattern = ["gh", "pr", "view"],
# The action to take when Codex requests to run a matching command.
decision = "prompt",
# Optional rationale for why this rule exists.
justification = "Viewing PRs is allowed with approval",
# `match` and `not_match` are optional "inline unit tests" where you can
# provide examples of commands that should (or should not) match this rule.
match = [
"gh pr view 7888",
"gh pr view --repo openai/codex",
"gh pr view 7888 --json title,body,comments",
],
not_match = [
# Does not match because the `pattern` must be an exact prefix.
"gh pr --repo openai/codex view 7888",
],
)decision의 기본값은 allow이고, 묻지 않고 막으려면 forbidden을 씁니다. 여러 규칙이 겹치면 forbidden > prompt > allow 순으로 가장 엄격한 결정이 적용돼요. TUI에서 명령을 허용 목록에 넣으면 코덱스가 ~/.codex/rules/default.rules에 기록해 다음부터 묻지 않습니다.
그런데 git add를 허용해 두면 git add . && rm -rf /도 통과할까요? 아닙니다. 변수나 리디렉션이 없는 단순한 연결 명령이면 코덱스가 명령을 둘로 나눠 각각 규칙에 맞춰 보고, 가장 엄격한 결과를 따릅니다. 반대로 리디렉션(>), 치환($(...)), 와일드카드가 들어간 스크립트는 나누지 않고 통째로 하나의 호출로 판단합니다.

규칙을 적용하기 전에는 실제로 어떻게 판정되는지 확인해 보세요.
codex execpolicy check --pretty \
--rules ~/.codex/rules/default.rules \
-- gh pr view 7888 --json title,body,comments인터넷 접속은 어떻게 열까요?
데스크톱 앱, CLI, IDE 확장의 기본 workspace-write 모드는 설정에서 켜지 않는 한 네트워크가 꺼져 있습니다. 앞 측정에서 curl이 실패한 것도 이 모드에서였죠. 켜는 설정은 다음과 같습니다.
[sandbox_workspace_write]
network_access = true접속할 곳을 제한하고 싶다면 network_proxy 기능을 함께 켭니다. 이 기능은 네트워크를 열어 주지 않고, 이미 열린 네트워크를 정한 정책 안으로 묶는 역할만 해요. 도메인 규칙을 추가해도 프록시가 저절로 켜지지는 않습니다.
[features.network_proxy]
enabled = true
domains = { "api.openai.com" = "allow", "example.com" = "deny" }
한 번만 실행할 때는 CLI에서 바로 지정할 수도 있습니다.
codex \
-c 'features.network_proxy=true' \
-c 'sandbox_workspace_write.network_access=true'도메인 규칙에서는 deny가 항상 allow보다 우선합니다. 전역 * 허용은 넓은 네트워크 접근과 같으니, 가능하면 범위를 좁힌 규칙을 쓰는 편이 낫습니다. 기본값 allow_local_binding = false에서는 루프백·사설 주소가 막히므로, 로컬 서버 하나만 필요하다면 localhost나 정확한 IP를 허용 규칙으로 넣으세요.
전체 접근 모드를 쓰기 전에 알아 둘 점
전체 접근은 sandbox_mode = "danger-full-access"와 approval_policy = "never"를 함께 쓰는 설정입니다. 파일 시스템과 네트워크 경계가 모두 사라지기 때문에, 문서는 에이전트에게 정말로 전체 접근을 맡길 때만 쓰라고 안내합니다. 승인 창이 귀찮다는 이유만으로 고를 설정은 아니라는 뜻이죠.
dangerously_allow_non_loopback_proxy와 dangerously_allow_all_unix_sockets도 신뢰 경계를 일부러 넓히는 설정이라 엄격히 통제된 환경에서만 써야 합니다. 혼자 여러 저장소를 오가며 작업한다면 접근 범위를 넓히기보다 프로젝트나 worktree를 나누는 쪽이 문서의 권장 방식입니다. 승인 범위를 고를 때도 작업을 이어 갈 수 있는 가장 좁은 범위(한 번만 승인 등)를 고르면 됩니다.
자주 하는 실수와 점검 목록
- 파이프 끝 명령의 종료 코드를 codex 결과로 읽는 경우:
tail이나ls를 파이프로 이으면 종료 코드는 마지막 명령의 값이 됩니다. codex가 성공했는지는 출력과 결과 파일로 확인하세요. - 읽기 전용인 줄 모르고 편집을 맡기는 경우: 에이전트가 직접 실행할 명령만 안내하고 끝납니다.
- 프록시만 켜고 네트워크는 켜지 않는 경우: 네트워크가 꺼져 있으면 프록시 기능은 아무 일도 하지 않습니다.
- 예전
untrusted승인 정책이 남아 있는 경우: 더 이상 지원하지 않는 값이라 클라이언트가 시작되지 않을 수 있습니다. 사용자·프로젝트 설정과 프로필 파일, 시작 스크립트에서 지우세요. 대화형 읽기 전용으로 쓰려면 문서 예시는 다음과 같습니다.
sandbox_mode = "read-only"
approval_policy = "on-request"마지막으로 아래 항목을 확인해 보세요.
- 지금 모드가 작업에 맞는가(
/permissions로 확인) - 작업 폴더 밖 쓰기는
writable_roots로만 열었는가 - 인터넷이 필요한 작업이면
network_access를 켰는가 - 반복 승인은 규칙 파일로 좁게 처리했는가
- 규칙은
codex execpolicy check로 판정을 확인했는가 - 설정 파일에
untrusted가 남아 있지 않은가
측정 조건과 한계
측정은 맥(darwin arm64) 한 대에서 codex-cli 0.164.0-alpha.11.1, Node.js v22.23.1로 진행했습니다. 모델은 GPT-6.1 Sol로 고정했고, --ignore-user-config로 사용자 설정(config.toml)을 불러오지 않았습니다. 각 단계는 한 번씩만 실행했기 때문에 걸린 시간은 그때의 값일 뿐, 모드끼리 속도를 비교할 근거는 되지 않습니다.
또 codex exec는 비대화형 실행이라 승인 창이 뜨는 과정은 이번 측정에 담기지 않았습니다. curl이 종료 코드 6으로 끝난 이유도 출력만으로는 단정하기 어렵습니다. 네트워크 설정을 켠 뒤 같은 명령을 다시 실행해 결과가 달라지는지 직접 비교해 보세요. 승인 정책의 자세한 동작은 Agent approvals & security에서 확인할 수 있습니다.
참고 자료
- Sandbox learn.chatgpt.com
- Agent approvals & security learn.chatgpt.com
- Rules learn.chatgpt.com