# Codex 샌드박스와 config.toml: 승인·쓰기·네트워크 경계

> Codex sandbox와 approval policy를 구분하고 최소 권한으로 파일과 네트워크를 설정한 뒤 macOS, Windows, WSL2, Linux 오류를 올바른 계층에서 진단합니다.

- Source: https://www.aifreeapi.com/ko/posts/codex-config-toml
- Language: ko
- Published: 2026-08-15
- Updated: 2026-08-16
- Publisher: AI Free API (https://www.aifreeapi.com)

Codex 샌드박스는 local command의 기술적 실행 경계입니다. command가 쓸 수 있는 파일과 network access를 제한합니다. `approval_policy`는 별도 제어로, 경계를 넘어야 할 때 Codex가 언제 멈춰 승인받을지 정합니다. 하나를 바꾼다고 다른 하나가 자동으로 바뀌지는 않습니다. 공식 [Sandbox 문서](https://learn.chatgpt.com/docs/sandboxing)는 Codex가 실행한 `git`, package manager, test runner도 같은 경계를 상속한다고 설명합니다.

일반적인 local development라면 `workspace-write`와 `on-request`에서 시작할 수 있습니다. workspace 안의 routine task는 계속 진행하고, 실제 경계를 넘어야 할 때 approval을 요청합니다. `read-only`는 점검용입니다. `danger-full-access`는 filesystem과 network sandbox를 제거하므로 install 실패나 path 오류의 일반적인 해결책이 아닙니다. 또한 `approval_policy = "never"`는 질문하지 않는다는 뜻이지, 그 값 하나로 full access를 허용한다는 뜻이 아닙니다.

그다음 설정 소유자를 정합니다. 개인 기본값은 `~/.codex/config.toml`, trusted repository 동작은 `.codex/config.toml`, 반복 mode는 profile, 일회성 값은 CLI override가 담당합니다. 권한 문제 하나를 고치려고 “완성형” 파일을 복사하면 model, provider, network, feature, MCP까지 동시에 바뀌어 원인을 잃을 수 있습니다.

수정 전에는 대상 파일만 백업하세요. 하나의 잘못된 table 때문에 `~/.codex` 전체를 지우면 정상적인 auth, profiles, rules까지 잃을 수 있습니다.

## 먼저 실제로 이기는 값을 찾는다

Codex는 일반 값을 다음 순서로 적용합니다.

1. CLI flag와 `--config`
2. trusted project의 `.codex/config.toml` — 현재 디렉터리에 가까운 레이어 우선
3. `--profile`로 선택한 파일
4. 사용자 `~/.codex/config.toml`
5. Unix의 `/etc/codex/config.toml`
6. built-in default

이 순서는 공식 [Configuration precedence](https://learn.chatgpt.com/docs/config-file/config-basic#configuration-precedence)에 명시되어 있습니다. user config를 바꿨는데 그대로라면 파일 저장보다 먼저 project/profile/CLI override를 확인해야 합니다.

![Codex 설정이 CLI, project, profile, user, system, default 순으로 적용되는 레이어 스택](https://www.aifreeapi.com/posts/ko/codex-config-toml/img/layer-stack.webp)

| 원하는 결과 | 적절한 위치 | 주의점 |
|---|---|---|
| 개인 model, reasoning, 알림, 개인 MCP | user config | 여러 repo에 공통 적용 |
| 한 repo의 실행 경계 | trusted project config | 신뢰하지 않은 repo에서는 로드되지 않음 |
| read-only review 같은 반복 모드 | 별도 profile | base 전체를 복제하지 않음 |
| 일회성 비교 | CLI override | 영구값으로 남지 않음 |
| 조직이 강제할 보안 정책 | managed requirements | 일반 local config로 우회하지 않음 |

project config가 모든 값을 이길 수 있는 것은 아닙니다. machine-local provider/auth, profile 선택, notification, telemetry 계열은 프로젝트가 덮어쓸 수 없습니다. 현재 목록에는 `model_provider`, `model_providers`, `profile`, `otel` 등이 포함됩니다. 정확한 키는 [Configuration reference](https://learn.chatgpt.com/docs/config-file/config-reference#configtoml)에서 확인하고 user 레이어에 둡니다.

## sandbox mode와 approval을 따로 선택한다

안전한 기본값은 두 줄로도 충분합니다.

```toml
approval_policy = "on-request"
sandbox_mode = "workspace-write"
```

세 설정은 책임이 다릅니다.

| 제어 | 결정하는 것 | 결정하지 않는 것 |
|---|---|---|
| `sandbox_mode` | command가 접근할 filesystem과 network | 경계에서 approval이 표시되는지 |
| `approval_policy` | 언제 멈춰 승인받는지 | 해당 action이 기술적으로 가능한지 |
| `approvals_reviewer` | eligible approval의 reviewer | sandbox 범위 자체 |

현재 공식 mode는 `read-only`, `workspace-write`, `danger-full-access`이고, 일반 approval policy는 `untrusted`, `on-request`, `never`입니다. CLI에서는 `/permissions`, IDE와 desktop app에서는 composer 아래 control로 active permissions를 바꿀 수 있습니다. 표시되는 option은 version이나 조직 정책에 따라 달라질 수 있으므로 [How permissions work](https://learn.chatgpt.com/docs/sandboxing#how-permissions-work)를 기준으로 확인합니다.

두 번째 repository만 써야 한다면 host 전체를 열지 말고 writable root를 추가합니다.

```toml
sandbox_mode = "workspace-write"
approval_policy = "on-request"

[sandbox_workspace_write]
writable_roots = ["/absolute/path/to/second-repo"]
network_access = false
```

home directory나 disk root를 넣으면 경계가 지나치게 넓어집니다. `network_access`는 workspace-write sandbox 안의 subprocess가 outbound network를 사용할 수 있는지 정합니다. web search, apps, MCP, remote browser와는 다른 control입니다. browser 조회가 된다고 `npm install`이나 API test process도 internet에 연결된다는 뜻은 아닙니다.

## 같은 mode도 OS에 따라 준비 조건이 다르다

신뢰 모델은 같지만 enforcement는 platform-native입니다. 공식 [Getting started](https://learn.chatgpt.com/docs/sandboxing#getting-started)에 따라 먼저 확인할 지점이 달라집니다.

| 환경 | 구현 | 권한을 넓히기 전 확인 |
|---|---|---|
| macOS | built-in Seatbelt | target path가 workspace 안인지 |
| native Windows | Codex native Windows sandbox | sandbox setup과 device policy |
| WSL2 | Linux sandbox implementation | WSL2와 `bubblewrap` |
| Linux | `bubblewrap`과 OS isolation | `bwrap`, user namespace, AppArmor |

Ubuntu/Debian은 distribution package를 먼저 설치합니다.

```bash
sudo apt install bubblewrap
```

Fedora는 다음과 같습니다.

```bash
sudo dnf install bubblewrap
```

설치 후에도 user namespace나 AppArmor 경고가 남으면 system-wide 제한을 먼저 끄지 말고 공식 문서의 distribution별 절차를 확인하세요. Docker 안에서는 outer container가 `bwrap`에 필요한 namespace나 seccomp를 막을 수 있습니다. 외부 container가 원하는 isolation을 제공하는지 확인한 뒤 내부 Codex mode를 정해야 합니다. bare host에서 같은 full access를 사용하는 것과는 위험이 다릅니다.

## Feature는 기본값과 버전을 먼저 확인한다

feature를 영구히 켜기 전에 설치된 CLI가 그 이름을 알고 있는지 확인합니다.

```bash
codex features list
codex features --help
```

현재 공식 config 문서는 `apps`, `goals`, `hooks`, `fast_mode`, `multi_agent` 등 일부 feature의 maturity와 default를 표시합니다. 기본으로 켜진 기능을 다시 `true`로 고정하면 얻는 것은 없고, 나중에 deprecated 키만 남을 수 있습니다. 목적이 명확할 때만 `[features]`에 값을 저장하세요.

profile도 현재 형식을 확인해야 합니다. 반복할 감사 모드는 별도 파일로 만듭니다.

```toml
# ~/.codex/audit.config.toml
model_reasoning_effort = "xhigh"
approval_policy = "on-request"
sandbox_mode = "read-only"
```

```bash
codex --profile audit
```

profile format은 client version에 따라 바뀔 수 있습니다. 오래된 `[profiles.name]` 예제를 복사하기 전에 현재 [Advanced Config: Profiles](https://learn.chatgpt.com/docs/config-file/config-advanced#profiles)를 확인하세요.

## MCP는 table, transport, auth, tool을 나눠 본다

STDIO server 예시는 command와 전달할 환경 변수를 분명히 둡니다.

```toml
[mcp_servers.docs]
command = "docs-server"
args = ["--read-only"]
env_vars = ["DOCS_TOKEN"]
startup_timeout_sec = 20
tool_timeout_sec = 60
enabled = true
```

Streamable HTTP server는 URL과 token source를 분리합니다.

```toml
[mcp_servers.tasks]
url = "https://mcp.example.internal/mcp"
bearer_token_env_var = "TASKS_MCP_TOKEN"
enabled = true
```

실제 token을 repo, 글, 지원 메시지에 붙여 넣지 마세요. OpenAI의 [MCP documentation](https://learn.chatgpt.com/docs/extend/mcp)은 STDIO, streamable HTTP, OAuth, environment header, timeout, tool allow/deny를 각각 정의합니다.

설정 후에는 설치 버전이 제공하는 명령으로 읽힌 server를 확인합니다.

```bash
codex mcp list
codex mcp --help
```

OAuth server는 `codex mcp login <server-name>`을 사용할 수 있습니다. 목록에 나온다는 사실은 table이 읽혔다는 뜻일 뿐, executable/URL, auth, 개별 tool의 정상 동작을 증명하지 않습니다.

## 오류 메시지보다 앞선 경계를 확인한다

최근 CLI는 `--strict-config`와 `doctor`를 제공합니다. 설치 버전에서 실제 지원되는지 먼저 확인하세요.

```bash
codex --version
codex --help
codex doctor --help
```

지원된다면 read-only 점검을 실행할 수 있습니다.

```bash
codex --strict-config doctor --summary
```

strict config는 인식하지 못하는 field를 오류로 만들고, doctor는 installation, config, auth, runtime 상태를 살핍니다. 이것이 성공해도 provider request나 MCP tool이 성공했다는 뜻은 아닙니다.

![Codex 오류를 file, parse, precedence, permission, provider, MCP 체크포인트로 분리한 진단 보드](https://www.aifreeapi.com/posts/ko/codex-config-toml/img/debug-checkpoints.webp)

| 증상 | 첫 체크포인트 |
|---|---|
| 한 repo에서만 값이 무시됨 | trust와 가까운 `.codex/config.toml` |
| CLI는 되지만 IDE는 key가 없음 | IDE process의 environment visibility |
| unknown field로 시작 실패 | client version과 current reference |
| repo를 읽지만 파일은 못 고침 | active sandbox와 정확한 workspace root |
| package install 또는 API test만 network 실패 | subprocess network, proxy/DNS, approval |
| native Windows sandbox setup 실패 | native/WSL2 경로와 device policy |
| model을 바꿨는데 route가 유지됨 | `model_provider`, profile, project, CLI |
| MCP는 보이지만 tool을 못 씀 | command/URL, auth, timeout, tool |
| 회사 장비에서 고권한 모드가 거부됨 | 관리되는 `requirements.toml` |

Business/Enterprise 관리 환경에서는 `requirements.toml`이 approval, permission profile, web search, MCP allowlist, plugin, feature를 제한할 수 있습니다. local 값이 강제 규칙과 충돌하면 허용된 값으로 fallback하고 알림을 표시할 수 있습니다. [Admin-enforced requirements](https://learn.chatgpt.com/docs/enterprise/managed-configuration#admin-enforced-requirements-requirementstoml)에 설명된 정책이므로 다른 local 파일로 옮겨 우회할 문제가 아닙니다.

한 번의 수정에는 하나의 관찰 가능한 목표만 두세요. 먼저 read, workspace 안의 한 번의 write, project-owned test를 증명한 뒤 실제로 필요한 directory나 network만 확인합니다. 이렇게 하면 config 미로드, 정상적인 sandbox 거부, approval 미표시, OS의 sandbox 생성 실패를 서로 분리할 수 있습니다.

설정법이 아니라 coding agent 선택이 필요하다면 [Claude Code와 Codex 비교](/ko/posts/claude-code-vs-codex)를 참고하세요.
