# How Sandbox Permissions Work in the OpenAI Codex Plugin: Read-Only vs Workspace-Write

> Understand OpenAI Codex plugin sandbox permissions: learn how read-only and workspace-write modes control file access and prevent network exfiltration.

- Repository: [OpenAI/codex-plugin-cc](https://github.com/openai/codex-plugin-cc)
- Tags: deep-dive
- Published: 2026-07-04

---

**The Codex plugin isolates every AI operation inside a sandbox that offers two permission levels: `read-only` (filesystem inspection only) and `workspace-write` (allows file modifications), with both modes disabling network access to prevent data exfiltration.**

The openai/codex-plugin-cc repository implements a robust sandboxing system that governs how AI agents interact with the host filesystem. Understanding these sandbox permissions is essential for securely deploying automated code generation, refactoring, and review workflows.

## Sandbox Permission Levels Explained

The plugin supports two distinct permission strings that determine the AI agent's capabilities:

- **`read-only`** — The agent can read files within the repository but **cannot write** any changes. Network access is disabled. This mode suits code review and suggestion tasks where the model only needs to inspect the codebase.
- **`workspace-write`** — In addition to read capabilities, the agent may **create, modify, or delete** files within the workspace. Network access remains disabled. This mode is required for automated refactoring, patch application, and file generation tasks.

The permission is expressed as a string value in the `sandbox` field of the request payload sent to the Codex app-server.

## Where Sandbox Permissions Are Configured

### Default Behavior in codex.mjs

If the caller does not explicitly specify a sandbox mode, the plugin defaults to `read-only` to ensure safe operation. In `plugins/codex/scripts/lib/codex.mjs`, the `buildThreadParams` and `buildResumeParams` functions implement this fallback using the nullish coalescing operator:

```javascript
// plugins/codex/scripts/lib/codex.mjs
// Lines 68-82
sandbox: options.sandbox ?? "read-only",

```

This guarantees that omitting the sandbox parameter never accidentally grants write access.

### Explicit Control in codex-companion.mjs

Higher-level logic in the companion script determines the appropriate permission level based on user intent. When processing requests, `codex-companion.mjs` checks for a `write` flag to switch between modes:

```javascript
// plugins/codex/scripts/codex-companion.mjs
// Line 491
sandbox: request.write ? "workspace-write" : "read-only",

```

This implementation ensures that write permissions are only granted when the user explicitly requests code modifications.

### Test Fixtures Validation

The test suite exercises both configurations to verify security boundaries. In `tests/fake-codex-fixture.mjs`, the fake Codex harness constructs messages containing detailed sandbox definitions:

```javascript
// tests/fake-codex-fixture.mjs
// Lines 316, 350
sandbox: { type: "readOnly", access: { type: "fullAccess" }, networkAccess: false },

```

These fixtures confirm that both read-only and write-capable sandboxes are properly handled throughout the system.

## How Permissions Are Enforced at Runtime

The app-server receives the sandbox string in the RPC request and creates a process sandbox using the `process` helper located in `plugins/codex/scripts/lib/process.mjs`. This helper:

1. **Starts the child process** with a restricted environment that blocks network sockets.
2. **Mounts the filesystem** according to the permission level—mounting the repository as read-only for `"read-only"` mode, or as writable for `"workspace-write"`.

While the exact mount implementation resides in the internal `process.mjs` helper, the contract remains straightforward: the `sandbox` field value directly determines the filesystem permissions granted to the AI agent.

## Security Implications

**Read-only mode** provides a guarantee that the model cannot alter source code, making it safe for use in continuous integration pipelines or automated code review systems where suggestions should never modify the repository.

**Workspace-write mode** should only be enabled when the user explicitly authorizes code changes. Even in this mode, the plugin maintains network restrictions to prevent the AI from exfiltrating data or downloading unauthorized dependencies.

## Practical Code Examples

### Starting a Thread with Default Permissions

To initiate a read-only session, simply omit the sandbox parameter or explicitly set it to `"read-only"`:

```javascript
// Defaults to "read-only" when sandbox is omitted
await codex.startThread({
  cwd: "/repo/my-project",
  model: "gpt-5.4",
  // sandbox defaults to "read-only" per codex.mjs lines 68-82
});

```

### Enabling Write Access for File Modifications

When the task requires generating or modifying files, explicitly request `workspace-write` permissions:

```javascript
await codex.startThread({
  cwd: "/repo/my-project",
  model: "gpt-5.4",
  sandbox: "workspace-write",   // Allows file modifications
});

```

### Conditional Permission Logic

Implement permission selection based on user intent, matching the pattern used in the companion script:

```javascript
function handleUserRequest(request) {
  // request.write is true if user asked for code fixes
  const sandbox = request.write ? "workspace-write" : "read-only";
  return codex.startThread({ 
    cwd: request.cwd, 
    sandbox,
    model: "gpt-5.4"
  });
}

```

This corresponds directly to the logic implemented in `codex-companion.mjs` at line 491.

## Summary

- **Two permission levels**: `read-only` (inspection only) and `workspace-write` (file modifications allowed).
- **Default safety**: The system defaults to `read-only` in `plugins/codex/scripts/lib/codex.mjs` when no sandbox is specified.
- **Explicit escalation**: Write permissions require explicit opt-in via the `write` flag in `codex-companion.mjs`.
- **Network isolation**: Both modes disable network access; the distinction only affects filesystem permissions.
- **Runtime enforcement**: The `process.mjs` helper implements the actual filesystem restrictions using read-only or writable mounts.

## Frequently Asked Questions

### What happens if I don't specify a sandbox permission when starting a thread?

The Codex plugin automatically defaults to `read-only` mode. In `plugins/codex/scripts/lib/codex.mjs`, the code uses `options.sandbox ?? "read-only"` to ensure that undefined or null values always fall back to the safest permission level.

### Can the AI access the internet in workspace-write mode?

No. Both `read-only` and `workspace-write` modes disable network access. The `workspace-write` permission only affects filesystem capabilities (creating, modifying, or deleting files), not network connectivity. Network restrictions are enforced consistently across all sandbox configurations.

### How does the companion script decide which permission level to use?

The companion script checks the `request.write` boolean flag. If the user request indicates an intent to modify code (such as applying a fix or refactoring), the script sets `sandbox: "workspace-write"`; otherwise, it maintains `read-only` restrictions. This logic appears at line 491 of `plugins/codex/scripts/codex-companion.mjs`.

### Where is the actual filesystem restriction implemented?

While the permission string is defined in the request parameters, the enforcement occurs in `plugins/codex/scripts/lib/process.mjs`. This helper creates the child process with restricted mounts—read-only for `"read-only"` mode and writable for `"workspace-write"`—ensuring the kernel-level filesystem permissions match the requested sandbox level.