2025년 9월 제가 Codex 엔지니어링 팀에 합류했을 당시 Windows용 Codex에는 샌드박스가 구현되어 있지 않았습니다. 그래서 Windows 사용자가 OpenAI의 코딩 에이전트를 사용하려면 만족스럽지 않은 두 가지 선택지 중 하나를 골라야 했습니다.
- 코딩 에이전트가 실행하려고 하는 거의 모든 명령을 직접 승인하기: 매번 읽기 작업까지 승인해야 했기 때문에 비효율적이고 번거로웠습니다. 사용자가 이런 작업을 직접 처리하지 않아도 된다는 것이 Codex의 주요 장점인데, 이 방식은 그 장점을 살리기가 어려웠습니다.
- 전체 액세스 모드 활성화하기: Codex가 승인이나 제한 없이 모든 명령을 실행하도록 허용하는 방식으로, 마찰은 줄어들지만 그만큼 감독이 어려워집니다.
OpenAI의 코딩 에이전트 Codex는 CLI, IDE 확장 프로그램 또는 데스크톱 앱을 통해 개발자 노트북에서 실행됩니다. Codex는 컴퓨터 앞의 사용자와 클라우드에서 추론을 수행하는 모델 사이에서 대화를 조율합니다.
Codex는 기본적으로 실제 사용자와 같은 권한으로 실행되기에 사용자가 할 수 있는 작업은 Codex도 수행할 수 있습니다. 이는 강력한 기능이지만, 그만큼 잠재적인 위험도 있습니다. 코딩 모델은 하니스에 로컬 명령을 실행하라고 지시할 수 있으며, 테스트 실행부터 파일 읽기와 편집, Git 브랜치 생성까지 다양한 작업을 수행할 수 있습니다. 이 때문에 Codex의 기본 모드는 효과성과 안전성 사이에서 균형을 맞추도록 설계되어 있습니다. 이 모드에서 Codex는 거의 모든 위치의 파일을 읽을 수 있고 워크스페이스, 즉 Codex를 실행하는 디렉터리 안에서는 파일을 쓸 수 있습니다. 다만 사용자가 명시적으로 요청하지 않는 한 인터넷에는 접근할 수 없습니다. 파일 쓰기와 네트워크 접근을 안전한 범위 안에서 자동으로 제한하려면 이러한 제약을 실제로 강제하는 샌드박스 환경이 필요합니다.
샌드박스는 제한된 실행 환경입니다. 개발자가 Codex를 사용하면 컴퓨터의 운영 체제가 축소된 권한으로 명령을 실행하고, 그 제약은 프로세스 트리의 하위 프로세스까지 이어집니다. 모든 Codex 명령은 처음부터 샌드박스 안에서 실행되며, 여기서 생성되는 모든 하위 프로세스도 동일한 경계 안에 유지됩니다.
Codex가 효과적인 샌드박스를 구현하려면 컴퓨터 운영 체제 차원에서 강제되는 격리 기능이 필요합니다. 일부 운영 체제는 이러한 기능을 지원하는 유틸리티를 제공합니다. macOS의 Seatbelt, Linux의 seccomp나 bubblewrap이 대표적입니다. 하지만 Windows는 현재 이런 종류의 기능을 기본 제공하지 않습니다.
이에 따라 Windows에서도 다른 환경과 마찬가지로 Codex를 안전하고 쾌적하게 사용할 수 있도록 자체 샌드박스를 구현해야 했습니다.
Windows는 격리를 구현하기 위한 몇 가지 도구와 기본 구성 요소를 제공합니다. OpenAI는 AppContainer, Windows Sandbox, Mandatory Integrity Control 레이블링 등 여러 후보를 검토했지만, 요구 사항을 온전히 충족하는 해법은 없었습니다.
AppContainer
- 개념: AppContainer는 Windows의 기본 샌드박스로, 앱이 접근해야 하는 리소스를 사전에 명확히 정의할 수 있을 때 사용하는 기능 기반 격리 모델입니다.
- 검토 이유: 단순히 제한을 최대한 적용하는 방식이 아니라 운영 체제 차원에서 실제 경계를 제공한다는 점이 매력적이었습니다.
- 채택하지 않은 이유: Codex는 범위가 엄격하게 정해진 단일 앱이 아닙니다. Codex는 셸, Git, Python, 패키지 관리자, 빌드 도구뿐 아니라 에이전트가 필요하다고 판단하는 그 밖의 바이너리까지 활용하는 개방형 개발자 워크플로를 다룹니다. 실제로 AppContainer는 이 문제에 맞는 구조가 아니었습니다. 격리 기능은 강력했지만 '에이전트가 개발자처럼 작업하도록 허용하는' 방식보다는 훨씬 좁은 범주의 워크로드에 맞는 모델이었습니다.
Windows Sandbox
- 정의: Windows Sandbox는 Microsoft가 제공하는 일회용 경량 가상 머신입니다. 강력한 격리 경계를 갖춘 새 Windows 데스크톱 환경을 제공하며, 이 안에서 수행한 작업은 세션이 끝나면 모두 사라집니다.
- 검토 이유: Windows Sandbox는 분명 매력적인 선택지였습니다. AppContainer보다 임의의 소프트웨어와의 호환성이 훨씬 높고 보안 관점에서도 훨씬 더 강력한 보호 경계를 제공하기 때문입니다.
- 채택하지 않은 이유: Codex는 별도의 일회용 데스크톱 안이 아니라 사용자의 실제 체크아웃, 도구, 환경에서 직접 작동해야 합니다. 별도 환경을 사용하려면 추가 설정이 필요하고 호스트와 게스트 환경을 연결해야 합니다. 또한 제품 관점에서도 근본적인 한계가 있었습니다. Windows Sandbox는 Windows Home SKU에서 사용할 수 없기 때문입니다.
Mandatory Integrity Control(MIC) 무결성 레이블링
- 정의: Windows에는 '무결성 수준'이라는 개념이 있습니다. 낮음, 보통, 높음 같은 수준을 통해 시스템이 개체와 프로세스를 얼마나 신뢰할지 판단합니다. 기본 규칙은 일반 ACL에서 허용하더라도 낮은 무결성 수준의 프로세스는 더 높은 무결성 수준의 개체를 수정할 수 없다는 것입니다. 예를 들어 낮은 무결성 프로세스는 신뢰도가 낮은 것으로 간주됩니다. 따라서 개체가 이를 허용하도록 명시적으로 다시 레이블링되지 않는 한 Windows는 이 프로세스가 일반적인 중간 무결성 개체를 수정하지 못하도록 차단합니다.
- 검토 이유: MIC는 개념상 매우 깔끔해 보였습니다. Codex를 낮은 무결성 수준으로 실행하고 쓰기 가능한 루트 경로를 낮은 무결성 수준으로 다시 레이블링한 뒤, 나머지 모든 영역에서는 Windows가 쓰기 작업을 차단하도록 하는 방식입니다. 이렇게 하면 관리자 권한 없이도 실제 OS 메커니즘을 활용할 수 있을 것입니다.
- 채택하지 않은 이유: ACL과 마찬가지로 무결성 레이블은 실제 호스트 파일 시스템을 수정하며, 이 경우 의미상 변경 범위가 특히 큽니다. 워크스페이스를 낮은 무결성 수준으로 표시한다는 것은 단순히 Codex가 여기에서 파일을 수정할 수 있다는 뜻만은 아닙니다. 낮은 무결성 프로세스 전반이 해당 위치에 쓰기 작업을 할 수 있다는 뜻이기도 합니다. 실제 개발자 머신에서는 개발자가 작업 중인 디렉터리가 호스트의 저무결성 쓰기 대상으로 바뀌어 버리며, 이는 하나의 샌드박스 설계에 맞춰 신중하게 범위를 지정한 ACL을 부여하는 것보다 훨씬 더 위험합니다. 중간 무결성 수준의 개발자 도구가 계속 작동하더라도 워크스페이스의 기본 신뢰 모델은 통제하기 어렵고 정당화하기는 더 어려운 방식으로 바뀌게 됩니다.
이 모든 선택지가 적합하지 않다는 결론에 이른 뒤, OpenAI는 Windows 사용자에게도 안전하고 쾌적한 Codex 경험을 제공할 자체 솔루션을 설계하기 시작했습니다.
첫 번째로 동작한 프로토타입은 Windows의 여러 개념과 도구를 조합해 필요한 격리를 구현하는 방식이었습니다. 처음부터 내세운 중요한 목표 중 하나는 권한 승격 없이 작동하게 하는 것이었습니다. 다시 말해 Codex가 샌드박스를 설정하거나 실행할 때 사용자에게 관리자 권한을 요청하지 않아도 되게 하는 것입니다. 이를 위해 파일 쓰기와 네트워크 접근에 합리적인 제한을 두는 방법을 찾아야 했습니다.
파일 쓰기를 전혀 제한하지 않으면 안전상 문제가 생깁니다. 하지만 너무 강하게 제한하면 샌드박스가 오히려 사용자의 생산성을 방해하고, 모든 작업마다 승인을 요구하는 불편한 경험으로 이어집니다. OpenAI는 이 균형을 맞추기 위해 Windows의 두 가지 핵심 구성 요소인 SID와 쓰기 제한 토큰을 활용했습니다.
SID, 즉 보안 식별자는 Windows가 권한에 연결하는 ID입니다. 사용자마다 SID가 있고 그룹에도 SID가 있으며 단일 로그인 세션에도 고유한 SID가 할당됩니다. 예를 들어 현재 로그인된 세션에는 S-1-5-5-X-Y와 같은 SID가 할당될 수 있고, 로컬 관리자 그룹에는 S-1-5-32-544와 같은 SID가 할당될 수 있습니다.
Windows에서는 실제 사용자에 대응하지 않지만 ACL(액세스 제어 목록)에 포함될 수 있는 합성 SID도 만들 수 있습니다. ACL은 특정 파일이나 디렉터리를 누가 읽고 쓰고 실행할 수 있는지 정의합니다. 바로 이러한 특성 때문에 SID는 샌드박스를 구현하는 데 유용한 기본 요소가 됩니다. 머신의 다른 부분에 영향을 주지 않고 Codex 샌드박스 전용 SID를 만들 수 있기 때문입니다.
프로세스 토큰은 실행 중인 프로세스의 ID와 권한을 정의하는 Windows 보안 개체입니다. 이 토큰은 프로세스가 수행할 수 있는 작업을 결정합니다. 쓰기 제한 토큰은 특정 유형의 프로세스 토큰으로, Windows가 쓰기 작업에 추가 접근 검사를 수행하도록 합니다.
쓰기 작업이 성공하려면 다음 두 가지 조건을 모두 충족해야 합니다.
- 일반 사용자 ID, 즉 토큰 '소유자'에게 해당 작업을 수행할 권한이 있어야 합니다
- 토큰의 제한된 SID 목록에 포함된 SID 중 적어도 하나에 접근 권한이 부여되어 있어야 합니다
실제로 이 검사를 활용하면 ACL을 통해 샌드박스가 파일 시스템에서 수정 권한을 가질 범위를 정확히 지정할 수 있었습니다. 덕분에 쓰기 작업에 필요한 세밀한 제어가 가능했습니다.
SID와 쓰기 제한 토큰을 사용한 권한 비승격 샌드박스는 다음과 같이 동작했습니다.
- 샌드박스 설정 단계에서
sandbox-write라는 합성 SID를 만들었습니다. sandbox-writeSID에는 다음 위치에 대한 쓰기, 실행, 삭제 접근 권한을 부여했습니다.- 현재 작업 디렉터리
config.toml에 구성된 추가writable_roots
- 샌드박스 설정 단계에서는 같은 SID가 쓰기 가능 영역 안에서도 다음과 같이 읽기 전용으로 유지해야 하는 위치에는 쓰기 작업을 하지 못하도록 명시적으로 차단했습니다.
<cwd>/.git<cwd>/.codex<cwd>/.agents
- Codex는 제한된 SID 목록에
Everyone, 현재 로그인 세션 SID,sandbox-write합성 SID가 포함된 쓰기 제한 토큰으로 명령을 실행했습니다.
이 흐름으로 파일 쓰기 제한 문제는 상당 부분 해결할 수 있었고 좋은 선택지 같아 보였습니다. 이제 남은 과제는 샌드박스의 네트워크 접근을 제한하는 것이었습니다.
네트워크 접근 제한은 샌드박스의 중요한 요소입니다. 이 제한이 없으면 악성 코드가 머신의 데이터를 인터넷으로 유출할 수 있습니다. 다만 비승격 방식으로 구현하려 했기 때문에 네트워크 트래픽을 강하게 차단할 수 있는 선택지는 제한적이었습니다. Windows Firewall 같은 도구는 일반적으로 관리자 권한 없이는 설치할 수 없었습니다.
Windows Firewall을 사용할 수 없는 상황에서는 제어 가능한 범위를 제한할 수밖에 없었습니다. 그래서 개발자들이 실제로 사용하는 네트워크 연동 도구가 하위 환경에서는 기본적으로 연결에 실패하도록 만들고자 했습니다. Git 명령이나 패키지 설치 프로그램 등이 샌드박스 안에서 실행되면 실패하게 하고, 인터넷에 연결되는 작업은 사용자가 직접 승인하도록 하는 방식입니다. 핵심 아이디어는 명백한 우회 경로를 막는 것이었습니다. 프록시를 인식하는 트래픽은 작동하지 않는 엔드포인트로 보내고, Git의 HTTP(S) 전송도 같은 방식으로 처리하며, SSH를 통한 Git은 즉시 실패하도록 만들었습니다. 여기에 더해 작은 denybin 디렉터리를 PATH 앞부분에 추가하고 PATHEXT의 순서를 변경해 스텁 SSH 및 SCP 스크립트가 실제 바이너리보다 먼저 확인되도록 했습니다.
네트워크 접근을 제한하기 위해 다음과 같은 환경 변수 재정의를 적용했습니다.
HTTPS_PROXY=http://127.0.0.1:9ALL_PROXY=http://127.0.0.1:9GIT_HTTPS_PROXY=http://127.0.0.1:9NO_PROXY=localhost,127.0.0.1,::1GIT_SSH_COMMAND=cmd /c exit 1
이 방식으로 일반적인 도구 기반 트래픽은 상당 부분 막을 수 있었지만, 여전히 권고 수준의 제한에 그쳤습니다. 프로세스가 환경 변수를 무시하거나 PATH를 우회하거나 직접 소켓을 열 수도 있었기 때문입니다. 감수하기에는 너무 큰 위험이었습니다.
흥미로운 소프트웨어 구현이 대개 그렇듯, 첫 번째 프로토타입에도 장단점이 모두 존재했습니다. 이 시스템은 몇 가지 표준 Windows 기능만으로 필요한 작업을 수행했고, 파일 시스템 쓰기를 매우 명확하고 세밀하게 제어할 수 있었습니다. 비승격 방식으로 실행되었기 때문에 사용자가 과도한 관리자 권한 요청을 승인하거나 로컬 머신의 관리자 권한을 가지고 있을 필요도 없었습니다. 하지만 분명한 단점도 있었습니다. 그중 일부는 이 접근법을 최종 설계로 채택할 수 없게 만든 결정적인 이유가 되었습니다.
- 설정 속도: 워크스페이스 ACL을 적용하는 작업은 워크스페이스 디렉터리 토폴로지에 따라 비용이 커질 수 있습니다.
- 시스템 변경 범위: 개발자 시스템에 실제 ACL을 적용했지만, 적용된 ACL은 모두 샌드박스에서만 사용하는 사용자 지정 합성 SID에 연결된 것이기 때문에 시스템에 미치는 영향은 비교적 제한적이었습니다.
- 변경하기 어려운 의미 체계: 파일 기반 제한에 ACL을 사용하면 샌드박스의 의미 체계를 바꾸는 작업에 비용이 많이 들고 복잡해집니다. macOS에서는 Seatbelt를 구성하는 데 사용하는
.sbpl파일을 동적으로 생성하는 방식을 바꾸면 되지만, Windows 샌드박스에서는 ACL을 조정하기 위해 느리고 부담이 큰 작업이 필요할 수 있습니다. - 취약한 네트워크 보호: 앞서 설명했듯이 네트워크 제한은 권고 수준에 머물렀습니다. 자체 네트워킹 스택을 구현한 일부 프로그램은 충분히 우회할 수 있었고, 적대적인 코드를 견디도록 설계된 방식도 아니었습니다.
처음 세 가지는 에이전트형 작업 흐름을 지원할 만큼 유연한 사용자 지정 샌드박스를 만들다 보면 어느 정도 감수해야 하는 문제였습니다. 반면 네트워크 제한은 성격이 달랐습니다.
악의적인 에이전트가 환경 변수 기반 네트워크 제한을 쉽게 우회할 수 있을 뿐 아니라 정상적인 코드나 바이너리도 환경 프록시 변수를 따르지 않거나 자체 소켓 기반 네트워크 코드를 구현한 경우에는 이 제한을 우회할 수 있었습니다. OpenAI는 이 문제만으로도 더 나은 샌드박스 모드에 투자할 이유가 충분하다고 판단했습니다.
팀은 더 강력하게 네트워크를 제한하기 위해 Windows Firewall을 사용하고자 했습니다. Windows Firewall은 사용자 또는 프로그램 단위로 아웃바운드 네트워크 트래픽을 차단할 수 있습니다. 하지만 몇 가지 이유로 Codex 하니스가 생성한 명령에만 적용되는 실용적인 방화벽 규칙을 만들기는 어려웠습니다.
- Windows는 제한된 토큰 안에 들어 있는 보조 식별자를 기준으로 방화벽 규칙을 매칭할 수 없습니다. 즉, '제한된 SID 목록 가운데 OpenAI의 합성 SID가 들어 있는 모든 토큰'에만 적용되는 규칙은 만들 수 없었습니다.
- 특정 바이너리에 매칭되는 방화벽 규칙을 만들 수는 있었지만, 그렇게 해도
codex.exe자체의 네트워킹만 제한할 수 있었습니다. Git이나 Python 프로세스 같이 에이전트가 사용자를 대신해 생성하는 프로세스에는 적용되지 않았습니다. - 다른 방화벽 매칭 기준도 이 문제에는 적합하지 않았습니다. 사용자 기준 규칙은 비승격 설계에서 제한된 자식 프로세스만 골라 매칭하지 못하고, 그 프로세스를 실행한 실제 Windows 사용자에 매칭됐습니다. 프로그램 경로 규칙은 범위가 너무 넓었습니다.
codex.exe나python.exe전체를 차단할 수는 있어도, 샌드박스 안에서 이루어진 특정python.exe실행만 차단할 수는 없었습니다. 포트나 주소 기반 규칙도 원하는 정책과 맞지 않았습니다. 우리가 원한 것은 443 포트처럼 특정 포트를 차단하는 방식이 아니라 제한된 프로세스 트리에서 발생하는 외부 네트워크 접근 전반을 차단하는 것이었습니다.
샌드박스 안에서 실행되는 명령에만 방화벽 규칙을 적용하려면 해당 명령을 실제 사용자가 아닌 별도의 주체로 실행해야 했습니다. 이 접근 방식은 팀을 새로운 방향으로 이끌었고, 그 과정에서 '권한 승격 없음'이라는 제약도 완화하게 되었습니다.
현재 구현인 다음 버전의 샌드박스는 설정 단계에서 관리자 권한 승격이 필요합니다. 그래서 저는 이것을 '권한 승격 샌드박스'라고 부릅니다. Codex가 시스템에서 명령을 생성하는 경계만 보면 권한 승격 샌드박스는 비승격 샌드박스와 비슷해 보입니다. 여전히 제한된 토큰으로 자식 프로세스를 실행하며, 마찬가지로 [Everyone, Logon, Synthetic]과 같은 제한된 SID 목록을 가진 write_restricted 토큰을 사용합니다. 다만 이 토큰의 주체는 더 이상 실제 Windows 사용자가 아닙니다. Codex가 직접 만든 다음 두 로컬 사용자 중 하나가 주체가 됩니다.
CodexSandboxOffline(방화벽 규칙이 적용되는 사용자)CodexSandboxOnline(방화벽 규칙이 적용되지 않는 사용자)
겉보기에는 작은 차이처럼 보이지만, 이 변화는 샌드박스 자체와 사용할 수 있는 대상, 설정 및 런타임 실행의 복잡성에 큰 영향을 미칩니다.
방화벽 규칙과 전용 Windows 사용자가 추가되었다는 점을 제외하면 시각적으로는 비승격 프로토타입과 비슷합니다. 실제로 명령을 실행하는 주체는 이 전용 사용자입니다. 다만 이러한 새로운 개념이 도입되면서 샌드박스가 명령을 실행하고 보호하기 전에 더 많은 설정 작업이 필요해졌습니다.
권한 비승격 샌드박스 설계의 설정 단계는 비교적 간단했습니다.
- 필요한 경우 합성 SID 생성
- 샌드박스 쓰기용 합성 SID에 ACL 적용
하지만 권한 승격 샌드박스에서는 더 많은 작업이 필요합니다.
- 아직 생성되지 않았다면 합성 SID 생성
- 아직 생성되지 않았다면 온라인 및 오프라인 샌드박스 사용자 생성
- 새로 생성된 사용자의 자격 증명을 로컬에 저장하고, 샌드박스 사용자가 실제로 읽을 수 없는 위치에서 Windows Data Protection API(DPAPI)로 암호화
CodexSandboxOffline사용자의 모든 아웃바운드 네트워크 접근을 차단하는 방화벽 규칙을 생성하거나 이미 존재하는 경우 올바르게 설정되어 있는지 검증
설정 단계에는 또 다른 까다로운 문제가 있습니다. Codex 샌드박스는 실제 Windows 사용자와 동등한 읽기 접근 권한을 가져야 합니다. 제한된 토큰의 주체 SID가 Windows 사용자였던 비승격 샌드박스에서는 이 조건이 자연스럽게 충족되었습니다. 하지만 주체가 새로운 CodexSandbox 사용자로 바뀌면 이러한 권한이 자동으로 따라오지 않습니다. Windows의 많은 관련 디렉터리는 'Authenticated Users'에 읽기 및 실행 권한을 부여합니다. 사용자 프로필 디렉터리가 대표적인 예입니다. 기본적으로 Windows 사용자는 다른 Windows 사용자의 프로필 디렉터리를 읽을 수 없으므로 여러 상황에서 단순한 파일 읽기조차 실패하게 됩니다.
팀은 이를 해결하기 위해 샌드박스 설정 과정에 한 단계를 더 추가했습니다. 아직 ACL이 없을 수 있는 위치에서 샌드박스 사용자에게 읽기 ACL을 부여하는 단계입니다. 그 대상에는 다음과 같이 자주 사용되는 Windows 디렉터리가 포함됩니다.
C:\Users\<real-user>C:\Windows\C:\Program Files\C:\Program Files (x86)\C:\ProgramData\
이 디렉터리 목록은 필요한 경로를 최대한 추린 것이며, 각 디렉터리에 ACL을 설치하는 작업에는 상당한 비용이 들 수 있습니다. 그래서 사용자가 샌드박스 설정 단계에서 ACL 설치가 끝날 때까지 기다리지 않도록 이 로직은 비동기적으로 실행됩니다.
팀은 설정 로직을 별도 바이너리로 캡슐화했습니다. 필요할 때만 UAC 경계를 넘기 위한 목적도 있었지만, 더 근본적인 이유는 아키텍처에 있었습니다. 샌드박스 설정은 codex.exe와 본질적으로 다른 역할을 수행합니다. 설정 로직을 전용 바이너리에 두면 codex.exe를 일반적인 비승격 하니스로 유지할 수 있고, Windows 전용 설정 장치가 다른 플랫폼의 codex.exe까지 불필요하게 비대하게 만들지 않도록 할 수 있습니다. 또한 오래 걸릴 수 있는 설정 작업을 메인 프로세스의 수명과 분리하고, 샌드박스에 필요한 여러 설정 경로를 한곳에서 처리할 수 있습니다.
Windows의 사용자 및 토큰 로그인 경계가 동작하는 방식 때문에 권한 비승격 샌드박스에서처럼 제한된 토큰을 만들고 그 토큰으로 프로세스를 실행하는 방식을 그대로 유지할 수는 없었습니다. 다른 Windows 사용자로 명령을 실행하기 위해 처음 구상한 흐름은 다음과 같았습니다.
codex.exe는 실제 Windows 사용자로 실행됩니다. 그런 다음 Codex는 다음 작업을 순서대로 수행합니다.- 샌드박스 사용자로
LogonUserW(...)를 호출합니다. - 해당 샌드박스 사용자 토큰에
CreateRestrictedToken(...)을 호출합니다. - 제한된 샌드박스 사용자 토큰을 사용해
CreateProcessAsUserW(...)를 호출하고 최종 하위 프로세스를 실행합니다.
- 샌드박스 사용자로
그러나 실제로는 이 흐름이 CreateProcessAsUserW(...) 단계의 권한 장벽에 막혀 동작하지 않았습니다. 다시 말해 codex.exe는 샌드박스 사용자용 제한된 토큰을 만들 수는 있었지만, 실제 사용자 쪽 경계에서 그 토큰으로 하위 프로세스를 안정적으로 시작할 수는 없었습니다. 따라서 이미 샌드박스 사용자로 실행 중인 프로세스가 필요했습니다. 제한을 적용하고 최종 하위 프로세스를 시작하는 작업이 실제 사용자 쪽이 아니라 샌드박스 사용자 쪽 경계에서 이루어지게 하기 위해서였습니다.
이 요구 사항에 따라 codex-command-runner.exe라는 새 바이너리가 만들어졌습니다. 이 바이너리의 역할은 제한된 토큰을 만들고 요청된 명령을 실행하는 것뿐입니다. 팀은 codex.exe가 전체 흐름을 직접 처리하게 하는 대신, 다시 말해 실제 사용자 → 샌드박스 사용자 → 제한된 토큰 → 하위 프로세스 순서의 흐름을 모두 맡기는 대신, 실행 과정을 두 단계로 나누었습니다.
1단계
codex.exe가CreateProcessWithLogonW(...)를 호출해codex-command-runner.exe를 샌드박스 사용자로 실행합니다. 이 시점에는 아직 제한된 토큰을 사용하지 않습니다.
2단계
- 러너 내부에서
OpenProcessToken(GetCurrentProcess(), ...)이 러너 자신의 토큰을 엽니다. 이 토큰은 이미 샌드박스 사용자에 속해 있습니다. - 러너는
GetTokenInformation(...)을 호출해 샌드박스 로그인 SID를 추출한 다음,CreateRestrictedToken(...)을 호출해 최종 제한 토큰을 만듭니다. - 러너는 이어서 이 제한 토큰으로
CreateProcessAsUserW(...)를 호출해 실제 하위 프로세스를 실행합니다.
알베르트 아인슈타인은 "모든 것은 가능한 한 단순하게 만들어야 하지만, 지나치게 단순화해서는 안 된다"고 말했습니다. 권한 승격 샌드박스 설계도 이러한 원칙에 따라 각 문제를 충분히 해결했습니다. 최종 아키텍처는 앞서 살펴본 네 개의 계층으로 구성됩니다.
codex.exe자체- 권한 승격이 필요한 모든 설정 관련 작업을 처리하는
codex-windows-sandbox-setup.exe - 제한된 토큰으로 명령을 실행하는
codex-command-runner.exe - 하위 프로세스
처음 이 프로젝트를 맡았을 때만 해도, 이 작업이 결국 어떤 형태로 완성될지 뚜렷하게 예상하지 못했습니다. 우선 Codex와 운영 체제 사이의 경계에서 샌드박싱 기능을 구현하는 일부터 시작했습니다. 이 접근 방식은 macOS와 Linux에서 Codex 샌드박스가 구현된 방식과도 매우 유사했습니다.
하지만 Windows가 제공하는 구체적인 도구를 더 깊이 이해하고, 보안과 사용 편의성 사이에서 수많은 결정을 거치면서 여러 바이너리, 사용자 지정 사용자, 방화벽 규칙, 권한 승격이 필요한 설정 단계, 비동기 프로세스 등이 결합된 현재의 형태로 발전했습니다.
아주 단순한 시스템이라고 할 수는 없습니다. 하지만 이 복잡성을 이루는 각 요소는 모두 필요에 의해 추가되었습니다. 목표는 안전하면서도 가능한 한 사용자의 작업을 방해하지 않는 샌드박스를 만드는 것이었습니다.
Windows에서 Codex 사용자에게 좋은 경험을 제공하기 위해 OpenAI가 세운 목표는 유용성을 희생하지 않으면서도 안전한 샌드박스를 만드는 것이었습니다. Codex를 사용하는 핵심 이유는 에이전트가 사용자의 지속적인 관여 없이도 작업을 수행할 수 있게 하는 데 있기 때문입니다.
이 프로젝트에서 얻은 가장 큰 교훈 중 하나는 Windows가 '안전한 자율 코딩 에이전트'에 딱 맞는 단일 기본 요소를 제공하지 않는다는 점이었습니다. 팀은 여러 도구와 개념을 조합해 일관된 시스템을 만들어야 했습니다. 초기 아이디어 중 일부는 막다른 길이었고, 최종 설계는 문제의 각 부분을 해결했던 초기 프로토타입들을 결합한 하이브리드에 가까웠습니다.
또 다른 교훈은 코딩 에이전트의 보안이 전통적인 애플리케이션 보안과는 성격이 다르다는 점이었습니다. Codex는 실제 개발자 워크플로에서 작동해야 합니다. 따라서 엔지니어링의 핵심은 에이전트형 워크로드와의 호환성과 실제로 강제할 수 있는 보안 경계 사이에서 균형을 잡는 것이었습니다. 이 긴장이 최종 설계의 트레이드오프를 결정했습니다.
Codex 샌드박스가 실제로 어떻게 작동하는지 궁금하신가요? 여기서 직접 사용해 보세요.


