OpenAI Codex · Code Mode

Windows: 제한 토큰, 방화벽 필터, 전용 시스템 사용자 둘

seatbelt도 없고 bubblewrap도 없어요. Windows 샌드박스는 세 관문을 겹친 거예요. 토큰이 쓰기를 맡고, 전용 계정이 당신이 누구인지를 맡고, WFP가 그 신원으로 네트워크를 걸러요. AppContainer는 이 권한 모델에 맞지 않고, 세트 전체는 기본이 꺼져 있어요.

강의 목표읽고 나면 세 가지를 말할 수 있어요. Windows에서 왜 신원으로만 자원을 잠글 수 있는지. 제한 토큰의 깃발 세 개가 왜 쓰기는 잡고 읽기와 네트워크는 못 잡는지. 왜 전용 시스템 사용자가 둘인지, AppContainer는 왜 내려놓았는지.
먼저 한 번 써 보세요 · 요청 하나가 세 관문을 지나가요
동작과 단계를 바꿔, 요청이 어느 관문에서 멈추는지 보세요
동작
단계
Elevated가 읽기를 신원 관문에서 어떻게 막는지 먼저 보세요. RestrictedToken으로 내리면 같은 읽기가 통과해요.
이번 요청
C:\Users\you\.ssh\id_rsa 읽기
현재 신원
CodexSandboxOffline
관문 1 · 제한 토큰대기
깃발 셋이 토큰을 잘라요. 쓰기는 교차 검사를 통과해야 하고, 이 단계의 읽기는 여전히 현재 사용자를 따라가요.
관문 2 · 전용 시스템 사용자대기
Elevated여야 CodexSandboxOffline 또는 Online으로 로그인하고, 계정 ACL로 .ssh 같은 디렉터리를 파내요.
관문 3 · 방화벽 필터대기
오프라인 계정에만 지속 WFP를 설치해요. ICMP, DNS, SMB는 커널이 걸러 내고, 일반 아웃바운드는 아웃바운드 방화벽으로 가요.
재생을 눌러, 이 요청이 세 관문을 차례로 지나는 모습을 보세요.
논리 궤적 · 애니메이션 각 단계가 소스 어디에 대응하는지
  1. Windows 스위치가 꺼져 있으면 플랫폼 샌드박스는 빈 값을 돌려주고, 뒤에 래퍼를 씌우지 않아요manager.rs L62
  2. 샌드박스가 필요하면 자기 exe에 숨은 인자를 붙여 래퍼로 써요wrapper.rs L20
  3. 깃발 셋으로 제한 토큰을 잘라요. 특권을 깎고, LUA, 쓰기는 교차 검사를 통과해야 해요token.rs L480
  4. RestrictedToken 단계에서는 읽기 검사가 capability SID를 보지 않아요windows.rs L109
  5. Elevated는 전용 계정으로 먼저 로그인한 뒤, 그 토큰에서 아래로 잘라요runner_client.rs L348
  6. 계정 이름 둘은 하드코딩이에요. Offline과 Onlinesetup.rs L50
  7. 네트워크 정책이 꺼져 있거나 프록시를 쓰면 Offline 신원을 고릅니다setup.rs L706
  8. 오프라인 계정에만 지속 WFP 필터를 설치해요wfp.rs L75
  9. 사용자 프로필 루트는 기본으로 .ssh 같은 디렉터리를 파내요setup.rs L56
  10. 백엔드가 없으면 읽기 전용 프로필에 Never를 더하고, 매칭되지 않은 명령은 Forbidden이어야 해요exec_policy_windows_tests.rs L113
재생을 눌러, 이 요청이 세 관문을 차례로 지나는 모습을 보세요.
토큰 단계는 쓰기만 잠가요RestrictedToken은 현재 사용자에서 토큰을 잘라요. 워크스페이스 밖 파일을 읽거나 밖으로 네트워크를 보내는 일은 둘 다 통과해요. 막으려면 Elevated로 바꿔야 해요.
신원 관문에서야 파냅니다.ssh는 사용자 프로필 제외 목록에 있어요. 전용 계정으로 로그인한 뒤에야 이 ACL이 살아나요.
네트워크는 SID에 걸려 있어요WFP는 오프라인 계정에만 설치돼요. 토큰 단계에는 계정 둘이 없어서 세 번째 관문 자체가 없어요.
수업용 스케치: 경로와 계정 이름은 수업용 설정이에요. 논리 궤적 오른쪽 행 번호는 openai/codex 저장소 commit 4f39251a01에 대응해요.
아이디어 1 · 프로세스 뷰가 없으면 신원으로 자원을 잠가요
어떤 문제를 푸는가

동료가 Mac에서 Codex를 돌리면, 에이전트가 사용자 폴더의 SSH 개인키 경로를 건드리다 Seatbelt에 바로 막히고, 오류는 Operation not permitted예요. 같은 읽기를 Windows에 두면 Access is denied로 바뀌어요. Windows 샌드박스를 켜지 않은 기계로 바꾸면 이 명령은 ACL까지 가지도 못하고, execpolicy가 먼저 Forbidden 또는 Prompt로 판정해요.

기계 세 대, 같은 의도, 실패 세 가지. 모델이 보는 다음 문장이 다르니 다음 걸음도 따라 바뀌어요. Windows가 Unix와 같은 기본 샌드박스가 있는 척하면, 모델은 자신이 갇혀 있다고 계획하는데 실제 명령은 맨몸으로 달려요.

아이디어는 무엇인가

macOS는 이 프로세스가 어떤 경로에 어떤 동작을 할 수 있는지를 제한해요. Linux는 이 프로세스가 무엇을 보고 어떤 시스템 호출을 할 수 있는지를 제한해요. Windows에는 namespace도 seccomp도 없어요. Codex는 질문을 바꿉니다. 이 신원이 어떤 자원에 닿을 수 있는가.

토큰이 당신이 누구인지를 정해요. RestrictedToken 단계는 현재 사용자 토큰에서 자르고, Elevated 단계는 전용 계정으로 로그인한 뒤 그 토큰에서 자릅니다. 양쪽 끝은 같은 깃발 세트로 들어가요. DISABLE_MAX_PRIVILEGE, LUA_TOKEN, WRITE_RESTRICTED. 특권은 얇아지고, 쓰기는 일반 ACL과 restricting SID 교차 검사를 둘 다 통과해야 해요.

RestrictedToken 단계에서 읽기는 여전히 현재 사용자를 따라가요. 소스도 그렇게 적혀 있어요. WRITE_RESTRICTED 토큰의 capability SID deny-read ACE는 읽기 검사에 참여하지 않으니, 읽기 제한은 Elevated로 가야 하고 맨몸 실행은 바로 거절돼요.출처: codex-rs/windows-sandbox-rs/src/token.rs 480행;codex-rs/sandboxing/src/windows.rs 109–117행

macOS 프로세스가 할 수 있는 일을 잠가요 SBPL 텍스트 file-read 규칙이 거절해요 Operation not permitted Linux 프로세스가 볼 수 있는 것을 잠가요 bubblewrap 뷰 경로가 마운트에 없어요 No such file or directory Windows 이 신원이 닿을 수 있는 것을 잠가요 토큰 더하기 ACL 신원에 권한이 없어요 Access is denied
수업용 구조도: 같은 읽기인데 격리 세트 셋이 다른 층을 잠그고, 모델이 보는 실패 의미도 달라요.
왜 오래가는가

주체가 할 수 있는 일과, 객체를 누가 만질 수 있는지는 격리 원시 두 세트예요. 다른 언어로 다시 써도 Windows에는 호출할 bwrap이 없어요. 물을 질문은 그대로예요. 신원이 있는지, 그 신원이 무엇을 만지도록 허용됐는지.

래핑 방식도 같은 종류의 자기 호출이에요. Windows는 자기 exe에 숨은 인자 --run-as-windows-sandbox를 붙이고, Linux가 arg0을 바꾸는 것과 같은 생각이에요.출처: codex-rs/windows-sandbox-rs/src/wrapper.rs 20행

아이디어 2 · 신원 하나에는 네트워크 정책을 한 세트만 걸 수 있어요
어떤 문제를 푸는가

WFP는 Windows Filtering Platform, 커널 안의 패킷 필터 프레임워크예요. 방화벽 규칙과 함께 SID로 매칭해요. SID 하나에는 네트워크 정책 한 세트만 대응해요. 같은 신원이 “네트워크가 전혀 없음”과 “프록시를 쓰거나 나갈 수 있음”을 동시에 뜻할 수는 없어요.

아이디어는 무엇인가

그래서 로컬 사용자 둘을 네트워크 신원 둘로 씁니다. CodexSandboxOfflineCodexSandboxOnline. from_permissions는 프록시를 강제하거나 네트워크 정책이 꺼져 있으면 Offline을 고릅니다. 오프라인 신원은 아웃바운드 차단, 프록시 포트 허용 목록, 그리고 ICMP·DNS 53·DNS-over-TLS 853·SMB를 덮는 WFP 12개를 설치해요. 온라인 신원은 이 차단 세트를 설치하지 않아요.

Unix 네트워크 격리는 프로세스가 보는 NIC 뷰를 갈아끼워요. WFP는 프로세스가 호스트 네트워크 스택에 그대로 있고, 이 SID가 보내는 특정 트래픽만 막혀요. 프로세스는 여전히 NIC를 보고, 해석에 실패하고, 다른 포트에 연결할 수 있어요.

필터는 안정 GUID로 식별되고 지속 깃발을 달고 있어 재부팅 후에도 남아요. 제거와 충돌은 자동으로 뜯지 않아요. 저장소에는 사용자를 지우거나 WFP를 철거하는 함수가 없어요. WFP 실패는 치명적이지 않다고 적혀 있고, 방화벽 실패는 setup 전체를 실패로 만들어요.출처: codex-rs/windows-sandbox-rs/src/setup.rs 50–51행、706–714행;codex-rs/windows-sandbox-rs/src/wfp.rs 69–95행

SID 하나, 서로 싸우는 네트워크 정책 두 세트 같은 계정 네트워크가 전혀 없음 프록시를 쓰거나 나갈 수 있음 필터는 SID로 매칭해서 두 세트를 설치할 수 없어요 계정 둘, 네트워크 정책 두 세트 CodexSandboxOffline WFP 12개와 아웃바운드 차단 Online 이 차단 세트를 설치하지 않아요 아웃바운드
수업용 구조도: 네트워크 정책 단계가 둘이면 신원도 둘이 필요해요.
왜 오래가는가

신원으로 접근 제어를 하면, 신원 수가 정책 조합 수를 덮어야 해요. 네트워크 정책 단계가 둘이면 신원도 둘이에요. 출입 카드 두 장으로 건물 두 동에 들어가는 것과 같고, WFP라는 구체 API와는 상관없어요.

아이디어 3 · AppContainer는 맞지 않고 Elevated는 너무 비싸서 기본은 꺼 둬요
어떤 문제를 푸는가

왜 AppContainer를 안 쓰느냐고 물을 거예요. 기본 읽기 범위가 좁고, 임의 경로 읽기는 호스트 DACL을 고쳐야 해요. Codex는 workspace가 읽히고 플랫폼 루트가 읽히며 deny 목록으로 파내야 해요. 제한 토큰 더하기 ACL이 이 권한 모델에 더 맞아요. codex-rs/에서 AppContainer를 검색하면 업무 코드는 0건이에요. 대조 저장소 DeepSeek Harness는 같은 판단을 평범한 문장으로 적었어요. AppContainer는 임의 경로 읽기를 못 해요.

Elevated가 읽기와 네트워크까지 잡으려면 계정을 만들고 UAC를 띄우며 방화벽과 WFP를 고쳐야 해요. 기업 정책이 로컬 사용자 생성을 막을 수 있어요. 기본을 Disabled로 두면, 이 제품 마찰을 첫 활성화에 남겨 두는 셈이에요.

아이디어는 무엇인가

열거형 자체가 기본값을 꺼짐으로 적어요. windows.sandbox를 쓰지 않고 legacy flag 둘도 없으면 Disabled로 떨어져요. legacy flag는 이미 Removed로 표시돼 있어요.

codex-rs/protocol/src/config_types.rs297–302행
pub enum WindowsSandboxLevel {
    #[default]
    Disabled,
    RestrictedToken,
    Elevated,
}
소스 스냅샷 설명: 로컬 저장소 openai/codex 기준, 확인 파일 codex-rs/protocol/src/config_types.rs, commit 4f39251a01, 확인일 2026-08-22. 코드 블록은 소스 원문을 유지하고, #[default]Disabled에 못 박혀 있어요.

끄고 나면 플랫폼 샌드박스는 정말 사라져요. get_platform_sandbox(false)는 Windows에서 빈 값을 주고, select_initial은 그걸 SandboxType::None으로 바꿔요. 명령은 정책 층에서 여전히 막힐 수 있어요. Windows 테스트가 이걸 잠가요. 백엔드가 없으면 읽기 전용 프로필에 Never 승인을 더하고, 매칭되지 않은 cmd.exe /c dirDecision::Forbidden이어야 해요.출처: codex-rs/sandboxing/src/manager.rs 62–72행、301행;codex-rs/core/src/exec_policy_windows_tests.rs 113–130행

AppContainer 기본 읽기 범위가 좁아요 임의 경로는 호스트 DACL을 고쳐야 해요 이 권한 모델에 맞지 않아요 콤보 토큰이 쓰기를 잠가요 전용 계정이 읽기를 잠가요 WFP가 SID로 네트워크를 걸러요 UAC가 필요하고 로컬 사용자가 필요해요 기본 Disabled execpolicy가 받아 줘요
수업용 구조도: 쓸 수 있는 세트는 너무 비싸서 기본은 먼저 끄고, 정책 층이 맨몸 실행을 받아 줘요.
관문 셋. 하나는 쓰기를, 하나는 당신이 누구인지를, 하나는 이 신원이 어느 네트워크 문으로 나갈 수 있는지를 맡아요.
왜 오래가는가

격리 깊이는 설치 예산에 묶여 있어요. 모델이 저장소를 실수로 고치는 것만 막으면 현재 사용자 제한 토큰으로 충분해요. 비밀을 읽어 이 기계 밖으로 보내는 것까지 막으려면 읽기 제한과 신원 기준 네트워크 필터가 더 필요해요. 세울 수 없는 벽을 약속하면 모델과 사용자 모두 그 벽을 기준으로 결정해요.

플랫폼 능력이 다를 때 대외 문구는 실제로 켜진 그 층으로 써야 해요. macOS는 기본으로 Seatbelt가 있고, Windows 기본은 Disabled일 수 있어요. 샌드박스가 있다고 들으면 기계 세 대가 같은 벽이라고 생각해요.

가로 비교 · 같은 깃발 세트, 기꺼이 치를 대가 세 가지

DeepSeek Harness: 같은 깃발 세트, 쓰기 제한에서 멈춰요

DSH의 @deepseek-ai/dsh-sandbox-windows-acl은 같은 CreateRestrictedToken 깃발을 씁니다. DISABLE_MAX_PRIVILEGE | LUA_TOKEN | WRITE_RESTRICTED. README는 읽기·네트워크·프로세스 가시성이 제한되지 않는다고 쓰고, enforcementpartial이에요. 전용 계정을 만들지 않고 WFP도 설치하지 않아요.

설계 노트는 AppContainer를 거절한 이유를 못 박았어요. AppContainer 토큰에는 환경 읽기 권한이 없고, 임의 경로 읽기는 미리 허가해야 해서 harness 읽기 모델에 맞지 않아요. mxc가 거절된 이유는 OS 버전 하한이 너무 새롭고, 임의 경로 읽기는 여전히 호스트 DACL을 고쳐야 해서예요. Codex Elevated는 계정 둘과 WFP로 읽기와 네트워크 신원까지 넣었고, 대가는 설치 마찰과 제거 잔여물이에요. DSH가 고른 것은 설치되고 돌아가는 쪽이고, 읽기와 네트워크는 다른 메커니즘에 남겨 둬요.

DSH token.ts / win32-abi.ts / README / 설계 노트 확인 · 2026-08-22 · DSH · 샌드박스: seatbelt에서 실행 세계로

Claude는 실행을 거절하고, Grok은 플랫폼을 unknown으로 표시해요

Claude Code는 네이티브 Windows에 샌드박스가 없다고 분명히 적어요. 기업 정책이 샌드박스를 요구하고 샌드박스 없는 명령을 금하면 PowerShell은 바로 실행을 거절하고, 문구는 sandboxing is not available on native Windows예요. 격리 층이 있는 척하지 않아요. Grok Build의 샌드박스 crate는 플랫폼을 linux/landlockmacos/seatbelt로 쓰고 나머지는 unknown이에요. xai-grok-sandbox에서 AppContainer, RestrictedToken, CreateRestrictedToken을 검색하면 대응 구현이 없어요.

답은 세 단계로 나뉘어요. Claude와 Grok은 Windows에서 파일시스템 샌드박스를 하지 않아요. DSH는 쓰기 제한을 했고 설치되며, 읽기와 네트워크는 다른 메커니즘에 남겨 둬요. Codex는 신원·ACL·WFP·전용 계정을 전부 넣어서 마찰이 더 크고, 그래서 기본이 꺼져 있어요.

Claude PowerShellTool.tsx, Grok types.rs 확인 · 2026-08-22 · Grok · 샌드박스 Profile 다섯 가지
수업 실습
01

같은 읽기, 단계를 바꾼 뒤 어디에 걸리는지

데모 동작은 워크스페이스 밖 읽기에 두고, 단계를 Elevated에서 RestrictedToken으로 내리세요. 먼저 예측을 적어요. 어느 관문이 허용하고, 어느 관문이 사라지며, 끝이 Access is denied인지 통과인지. 그다음 재생을 눌러 맞춰 보세요.

심화 질문: 동작을 네트워크 보내기로 바꾸세요. RestrictedToken 단계에서 세 번째 관문이 왜 건너뛰기이고, Elevated 단계에서야 WFP가 켜지는 이유는 뭘까요.

Takeaway: Windows에는 seatbelt와 bubblewrap이 없어서 격리는 신원으로만 자원을 잠글 수 있어요. RestrictedToken 깃발 셋은 쓰기를 맡고 읽기와 네트워크는 맡지 않아요. 비밀과 아웃바운드를 막으려면 전용 계정, ACL, SID로 설치한 WFP가 더 필요해요. AppContainer는 이 읽기 집합에 맞지 않고 Elevated는 UAC를 원해서 기본은 꺼져 있고, 백엔드가 없으면 execpolicy가 Forbidden 또는 Prompt가 돼요.