How Sandbox Permissions Work in the OpenAI Codex Plugin: Read-Only vs Workspace-Write
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:
// 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:
// 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:
// 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:
- Starts the child process with a restricted environment that blocks network sockets.
- 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":
// 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:
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:
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) andworkspace-write(file modifications allowed). - Default safety: The system defaults to
read-onlyinplugins/codex/scripts/lib/codex.mjswhen no sandbox is specified. - Explicit escalation: Write permissions require explicit opt-in via the
writeflag incodex-companion.mjs. - Network isolation: Both modes disable network access; the distinction only affects filesystem permissions.
- Runtime enforcement: The
process.mjshelper 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →