Codex CLI 샌드박스 read-only와 workspace-write 차이 — 윈도우에서 파일 쓰기로 비교
같은 「hello.txt를 만들어 달라」 요청을 codex exec -s read-only와 -s workspace-write로 돌렸습니다. read-only에서는 쓰기가 막혀 파일이 생기지 않았고, workspace-write에서는 파일이 생겼습니다.
한 줄로
같은 「hello.txt를 만들어 달라」 요청을 codex exec -s read-only와 -s workspace-write로 돌렸습니다. read-only에서는 쓰기가 막혀 파일이 생기지 않았고, workspace-write에서는 파일이 생겼습니다. 두 경우 모두 종료 코드는 0이었으니, 성공 여부는 파일을 직접 확인해야 합니다.
이런 분께
codex exec를 자동화에 넣으면서 파일을 고치게 할지 말지 정하려는 분- 윈도우에서 read-only가 실제로 무엇을 막는지 로그로 보고 싶은 분
-s,-a같은 옵션이 어디에 있는지 헷갈리는 분
실측 환경
| 항목 | 값 |
|---|---|
| OS | Windows 11 Home (10.0.26200) |
| 셸 | Git Bash, PowerShell 7.6.6 |
| codex | codex-cli 0.153.4 |
| 모델(실행 머리말 표시) | gpt-6-astra |
| 작업 폴더 | 임시 폴더 아래 빈 폴더 sbx_ro, sbx_ww |
| 공통 옵션 | --skip-git-repo-check --ephemeral, < /dev/null로 stdin이 바로 끝나게 함 |
도움말에 있는 옵션
codex exec --help의 샌드박스·승인 관련 부분입니다.
-s, --sandbox <SANDBOX_MODE>
Select the sandbox policy to use when executing model-generated shell commands
[possible values: read-only, workspace-write, danger-full-access]
--approve-for-me
Route approval requests through automatic review using the workspace-write sandbox
--dangerously-bypass-approvals-and-sandbox
Skip all confirmation prompts and execute commands without sandboxing. EXTREMELY
DANGEROUS. Intended solely for running in environments that are externally sandboxed
--add-dir <DIR>
Additional directories that should be writable alongside the primary workspace-a, --ask-for-approval은 codex exec --help에는 없고, 최상위 codex --help에만 있었습니다.
-a, --ask-for-approval <APPROVAL_POLICY>
Configure when the model requires human approval before executing a command
Possible values:
- on-request: The model decides when to ask the user for approval
- never: Never ask for user approval Execution failures are immediately returned to
the modeldanger-full-access와 --dangerously-bypass-approvals-and-sandbox는 도움말만 옮겼고 실행하지 않았습니다.
공식 문서는 read-only와 workspace-write를 이렇게 설명합니다. "read-only : The agent can inspect files, but it can't edit files or run commands without approval. workspace-write : The agent can read files, edit within the workspace, and run routine local commands inside that boundary." (learn.chatgpt.com/docs/sandboxing, 2026-09-17 확인)
1. read-only로 돌리기
cd sbx_ro
codex exec --skip-git-repo-check --ephemeral -s read-only -o ../ro_last.txt \
'Create a file named hello.txt in the current working directory containing exactly: hello. Do not use any other directory. Then reply with one line: DONE if the file now exists, otherwise FAILED plus the error.' < /dev/null
echo "codex exit=$?"codex exit=0. 실행 뒤 파일 확인까지 포함한 전체 명령이 30.7초 걸렸습니다. 실행 뒤 폴더는 비어 있었고 hello.txt: not found가 찍혔습니다. 마지막 답은 이랬습니다.
FAILED: Access denied when creating hello.txt; the current directory is read-only.머리말은 approval: never, sandbox: read-only였습니다. 표준오류를 보면 codex가 PowerShell로 쓰기를 두 번 시도했고, 막힌 방식이 서로 달랐습니다.
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodInvocationNotSupportedInConstrainedLanguage
...
+ CategoryInfo : PermissionDenied: (C:\Users\User\A...bx_ro\hello.txt:String) [Set-Content], Unauthorized
AccessException
+ FullyQualifiedErrorId : GetContentWriterUnauthorizedAccessError,Microsoft.PowerShell.Commands.SetContentCommand첫 시도([System.IO.File]::WriteAllText)는 PowerShell이 메서드 호출 자체를 막았고, 둘째 시도(Set-Content)는 파일 접근 거부로 실패했습니다. 한글 오류 설명은 깨져서 읽을 수 없었습니다. 셋째 명령 Test-Path는 False를 내며 정상 실행됐습니다.
문서의 read-only 설명에는 승인 없이는 명령을 실행하지 못한다고 되어 있습니다. 이번 실행(approval: never)에서는 쓰기 시도 두 번과 Test-Path가 모두 실행됐고, 쓰기만 실패했습니다.
2. workspace-write로 돌리기
-s workspace-write와 -o ../ww_last.txt, 빈 폴더 sbx_ww만 바꾸고 같은 요청을 보냈습니다.
codex exit=0, 마지막 답 DONE. 파일 확인까지 포함한 전체 명령은 24.6초였습니다. 머리말에 쓰기 허용 범위가 함께 찍혔습니다.
approval: never
sandbox: workspace-write [workdir, /tmp, $TMPDIR]파일은 생겼는데 내용이 hello가 아니었습니다.
-rw-r--r-- 1 User 197121 6 Sep 17 18:13 hello.txt
hello.
68 65 6c 6c 6f 2eworkspace-write 실행에서 codex가 쓴 문자열은 'hello.'였고, read-only 실행에서 시도한 문자열은 'hello'였습니다. 요청문 containing exactly: hello.의 마침표를 두 실행이 서로 다르게 해석한 것으로 보입니다. 요청문을 쓸 때 내용은 따옴표로 감싸는 편이 낫습니다. read-only에서 막혔던 [System.IO.File]::WriteAllText 메서드는 이번에 인수를 달리해(UTF-8 인코딩 지정) 호출됐고, 성공했습니다.
두 모드의 PowerShell 환경 비교
두 모드에서 codex에게 같은 읽기 명령을 그대로 돌리게 했습니다.
$ExecutionContext.SessionState.LanguageMode; (Get-Command python -ErrorAction SilentlyContinue).Source; $env:USERNAME| 실행 위치 | LanguageMode | python 경로 | USERNAME |
|---|---|---|---|
샌드박스 밖(pwsh -NoProfile) | FullLanguage | C:\Users\User\AppData\Local\Programs\Python\Python312\python.exe | User |
codex -s read-only | ConstrainedLanguage | (출력 없음) | User |
codex -s workspace-write | FullLanguage | (출력 없음) | User |
read-only에서만 PowerShell이 ConstrainedLanguage로 돌았습니다. 1절의 MethodInvocationNotSupportedInConstrainedLanguage와 맞는 결과입니다. python 경로는 두 모드 모두 출력되지 않았습니다. 샌드박스 밖에서는 경로가 나왔으니, codex가 명령을 돌리는 환경에서만 안 잡힌 셈입니다. codex review로 커밋 전 리뷰에서 codex가 테스트를 돌리려다 python을 못 찾은 일도 따로 적었습니다.
윈도우에서 샌드박스는 어떻게 도나
codex sandbox --help의 인자 설명에 윈도우 방식이 적혀 있습니다.
[COMMAND]...
Full command args to run under Windows restricted token sandbox공식 문서의 윈도우 샌드박스 쪽은 두 방식을 설명합니다. "When you run Codex natively on Windows, agent mode uses a Windows sandbox to block filesystem writes outside the working folder and prevent network access without your explicit approval." 그리고 elevated는 "dedicated lower-privilege sandbox users"를, unelevated는 "a restricted Windows token derived from your current user"를 쓴다고 합니다(learn.chatgpt.com/docs/windows/windows-sandbox, 2026-09-17 확인). 이 PC가 둘 중 어느 쪽으로 돌았는지는 확인하지 않았습니다. 설정 파일을 열지 않았고, 위 표의 USERNAME 값만으로는 가릴 수 없습니다.
codex sandbox로 명령을 직접 돌려 보려던 시도는 세 번 모두 막혔습니다.
windows sandbox failed: runner failed during SpawnChild: CreateProcessAsUserW failed: 2 (지정된 파일을 찾을 수 없습니다.) | cwd=C:\Users\User\AppData\Local\Temp\longtail_A2 | cmd=windows --help | ...
error: the following required arguments were not provided:
--permission-profile <NAME>
Error: default_permissions requires a `[permissions]` table첫 줄은 codex sandbox windows --help를 쳤더니 windows를 실행할 명령으로 받아 샌드박스 안에서 실행을 시도한 결과입니다. 둘째 줄은 -P 없이 실행했을 때, 셋째 줄은 -P read-only를 줬을 때입니다. 설정 파일에 [permissions] 표가 있어야 하는 것으로 보여 여기서 멈췄습니다.
결과
| 회차 | 모드 | 종료 코드 | 걸린 시간 | hello.txt | 마지막 답 |
|---|---|---|---|---|---|
| 1 | -s read-only | 0 | 30.7초(전체 명령) | 안 생김 | FAILED: Access denied ... |
| 2 | -s workspace-write | 0 | 24.6초(전체 명령) | 생김(6바이트, hello.) | DONE |
| 3 | 두 모드 환경 확인(연속 실행) | 0, 0 | 35.3초(둘 합) | 해당 없음 | 표 참고 |
실패한 것
이번 read-only 실행은 파일 생성에 실패했다는 답을 돌려주면서도 종료 코드는 0이었습니다. 자동화에서는 새 파일과 내용을 직접 확인해야 합니다. 기존 제안의 test -f hello.txt || echo ...는 실패 문구를 찍고도 0으로 끝날 수 있으며, 이전 파일이나 내용이 틀린 파일도 통과시킵니다.
codex sandbox -P read-only 실행에서 [permissions] 표가 필요하다는 오류가 나, codex sandbox로 명령을 직접 넣어 보는 확인은 거기서 중단했습니다.
이번에 새로 확인함 — 2026-09-28
verify-new-output.sh를 현재 폴더에 저장하면 쓰기 검사를 실행할 수 있습니다. Bash·mktemp·cmp와 설치 및 로그인된 Codex가 필요합니다.
bash verify-new-output.sh write스크립트는 mktemp -d ./codex-check.XXXXXXXX로 만든 새 폴더에서 -s workspace-write로 요청합니다. 이번 요청은 내용 "hello"를 따옴표로 구분하고, 마침표·BOM·줄바꿈 없는 UTF-8 5바이트라고 명시합니다. Codex가 0이 아닌 값으로 끝나면 그대로 반환하고, 0이어도 hello.txt가 일반 파일인지(심볼릭 링크 제외)와 정확한 5바이트인지 cmp로 확인합니다. 누락·내용 불일치는 종료 코드 1, 성공은 verified: <새 폴더>/hello.txt와 0입니다. 검사 폴더와 답변 last.txt는 확인용으로 남깁니다. 매번 새 폴더를 쓰므로 기존 사용자 파일을 덮어쓰거나 예전 파일 때문에 통과하지 않습니다.
이번에는 Linux Bash `5.2.21`에서 검사기만 모의 시험했습니다. 시험용 생산자의 정상 파일은 0, 누락·빈 파일·틀린 내용·추가 줄바꿈·심볼릭 링크는 각각 1, 올바른 파일을 쓰고 37로 끝난 생산자는 37을 반환했습니다. 부모 폴더에 예전 hello.txt를 남겨도 누락 사례는 실패했고, 실행마다 다른 새 폴더를 확인했습니다. Codex 실행 파일·로그인·Windows가 없어 모델의 파일 생성이나 샌드박스 경계는 다시 검증하지 않았습니다. 위 2026-09-17 실측을 대체하는 결과가 아닙니다.
확인하지 않은 것
danger-full-access,--dangerously-bypass-approvals-and-sandbox,--approve-for-me는 실행하지 않았습니다.-a on-request처럼 사람이 승인하는 흐름은 시험하지 않았습니다.- workspace-write에서 작업 폴더 밖에 쓰기를 요청하면 어떻게 되는지는 시험하지 않았습니다. 이번 임시 폴더가
%TEMP%아래라, 머리말의$TMPDIR허용과 섞여 결과를 가리기 어렵다고 봤습니다. --add-dir, 네트워크 접근 차단은 확인하지 않았습니다.- 이 PC의 윈도우 샌드박스가
elevated인지unelevated인지는 모릅니다. - codex 안의 PowerShell에서
python이 안 잡힌 원인은 조사하지 않았습니다. - WSL, 맥·리눅스에서는 돌리지 않았습니다.