Skip to content

Hardcoded sandbox values always override config.toml sandbox_mode #482

Open

Description

@cubicj

Summary

The plugin sends an explicit sandbox value on every thread/start / thread/resume, so the sandbox_mode a user configured in ~/.codex/config.toml never applies to plugin-launched jobs. A user who sets sandbox_mode = "workspace-write" expecting delegated tasks to edit files still gets read-only unless every single invocation remembers --write; other config keys (model, reasoning effort) flow through to plugin jobs as defaults, but sandbox_mode is the one setting that silently cannot.

Evidence (at HEAD db52e28, plugin v1.0.6)

  • buildThreadParams and buildResumeParams always materialize a sandbox: sandbox: options.sandbox ?? "read-only" (plugins/codex/scripts/lib/codex.mjs:68, :81) — the config value can never surface.
  • Task path hardcodes the pair: sandbox: request.write ? "workspace-write" : "read-only" (plugins/codex/scripts/codex-companion.mjs:491).
  • Review paths pin read-only (codex.mjs:1012, codex-companion.mjs:414).
  • The app-server does fall back to config when the parameter is omitted. Verified live (Codex CLI 0.145.0-alpha.2) with a minimal JSON-RPC client:
    • thread/start with sandbox omitted → the response sandbox matched the sandbox_mode configured in config.toml, alongside the config-resolved model and reasoningEffort.
    • thread/start with sandbox: "read-only" → response sandbox: {"type":"readOnly","networkAccess":false}, overriding config as expected.

So the ?? "read-only" default and the two hardcoded call sites are the only thing standing between config.toml and plugin jobs.

Repro

  1. Set sandbox_mode = "workspace-write" in ~/.codex/config.toml.
  2. Run node scripts/codex-companion.mjs task --background "any prompt" without --write.
  3. The job executes read-only regardless of config. There is no flag, config key, or environment variable that lets the configured sandbox_mode through.

Proposed fix

When the caller passes no explicit sandbox-affecting flag, omit sandbox from the thread params and let the app-server resolve it from config.toml — the same fallback the app-server already performs for model and reasoning effort. --write stays as an explicit override, and the review paths can reasonably remain pinned read-only if reviews are meant to be side-effect-free; that call is yours.

An alternative shape with the same effect is a --sandbox <read-only|workspace-write|danger-full-access> passthrough on task, mirroring the Codex CLI's own --sandbox flag and defaulting to today's behavior.

Happy to follow up with a PR once a direction is picked.

Related

Environment

  • Plugin codex@openai-codex v1.0.6 (upstream HEAD db52e28)
  • Codex CLI 0.145.0-alpha.2
  • Claude Code on WSL2 Ubuntu 26.04, Node v24.18.0

Activity

  1. nayots commented on Jul 27, 2026

    @nayots

    Additional data point on the impact of the hardcoded value at codex-companion.mjs:491, from an A/B test on Windows. The consequence isn't only that sandbox_mode is ignored — under workspace-write the sandboxed commands appear to run as a different Windows security principal than the user, which breaks git independently of filesystem permissions.

    Setup. Windows 11, plugin v1.0.6, codex-cli 0.144.6, Node v26.3.0. Throwaway git repo; a background write task dispatched via codex-companion.mjs task --background --write --fresh --prompt-file …, asking Codex to create a file, git add it, then git commit. The only variable between the two runs was the value on line 491.

    A — as shipped (sandbox: request.write ? "workspace-write" : "read-only")

    Both git commands failed:

    fatal: detected dubious ownership in repository at '<repo>'
    '<repo>' is owned by:
            'S-1-5-21-<redacted>-1002'
    but the current user is:
            'S-1-5-21-<redacted>-1005'
    

    B — same line changed to "danger-full-access", nothing else touched

    [main de0cbc1] probe commit
     1 file changed, 1 insertion(+)
    

    Why this might be worth calling out separately from the config-override framing. The ownership error isn't a filesystem-permission denial, so the remedies people reach for don't apply:

    • trust_level = "trusted" and [windows] sandbox = "elevated" in config.toml change nothing — neither affects which principal the commands run as.
    • git's own suggested fix (git config --global --add safe.directory …) is a dead end, since the sandboxed git isn't reading the invoking user's global config.

    In a plan-driven workflow the user-visible symptom is that a task implements and verifies successfully and then cannot commit — surfacing as dubious ownership in some repos and Unable to create '.../.git/index.lock': Permission denied in others, apparently from the same cause. Any "one commit per task" discipline stalls at the first commit after all the work is done.

    This should resolve along with the config-override issue if a per-invocation sandbox selector lands, or if the parameter stops being sent unconditionally. Flagging the principal mismatch mainly because it makes the failure look like a git configuration problem rather than a sandbox one, which sends people down the wrong path.

  2. cubicj commented on Jul 28, 2026

    @cubicj
    Author

    @nayots
    Thanks for the A/B probe — the principal-mismatch detail is a good catch, and I agree it disguises a sandbox problem as a git configuration one. The linked PR #508 resolves this case: it stops sending the hardcoded sandbox value from codex-companion.mjs:491, so the failure you traced becomes reachable-by-configuration instead of baked in. Before replying I verified that on a Windows 11 host against the #508 branch (codex-cli 0.146.0-alpha.10, Node v24.16.0), alongside a protocol-level check of what the plugin actually sends.

    With #508, a task invoked with neither --write nor --read-only passes sandbox: null, and a thread/start probe against a directly spawned app-server confirms that resolves to whatever sandbox_mode is set in config.toml, with the response echoing the resolved policy. On Windows with sandbox_mode = "danger-full-access" and no sandbox flag, your probe sequence (create a file, git add, git commit) completed with the commit landing. The same task with --write still pins workspace-write and still fails on Windows — though on 0.146.0-alpha.10 it fails earlier than what you observed on 0.144.6: the file write itself is rejected with patch rejected: writing is blocked by read-only sandbox; rejected by user approval settings, so the run never reaches git. Same conclusion either way: workspace-write on Windows is not currently usable for write tasks, and #508's config-driven path is the one that works.

    Two clarifications on scope. An explicit --write still pins workspace-write by design — and in practice that flag comes from the delegating Claude session, not from anything you type: the plugin's skill guidance tells the model to add --write by default for write tasks, which is what produced the invocation in your A run. So the migration on Windows has two parts: set sandbox_mode = "danger-full-access" in config.toml, and instruct your Claude session (user-level CLAUDE.md works) not to pass sandbox flags so the config governs. And with no sandbox_mode configured at all, the flagless path resolves to read-only (the codex config default), which matches the plugin's pre-#508 default exactly — unconfigured setups see no behavior change, and the config override is what #508 adds.

    The write-rejection behavior under workspace-write on 0.146.0-alpha.10 looks like a codex-side regression or an intentional tightening of the Windows sandbox — either way it's independent of this plugin and probably worth tracking upstream.

  3. AzmainMahatab commented on Oct 8, 2026

    @AzmainMahatab

    Another data point from Windows 11 (codex-cli 0.161.0, plugin v1.0.6): with the plugin's forced sandboxes, every shell command in a task failed for me, while codex exec with the same config.toml worked. Two separate causes, both only reachable because the plugin pins the sandbox:

    • A Store/MSIX-installed PowerShell 7 (C:\Program Files\WindowsApps\...\pwsh.exe) cannot be started under the restricted-token sandbox (CreateProcessAsUserW error 5 / 1920).
    • With [windows] sandbox = "elevated", the setup refresh tries to update ACLs on the desktop app's running node_repl.exe and fails with os error 32 (file in use), so every command is rejected with helper_unknown_error: setup refresh had errors.

    Letting the sandbox and approval policy come from config (#646 for the sandbox, #806 for the approval policy) avoids both. Until something lands, I keep a patched build that tracks upstream releases: https://github.com/AzmainMahatab/codex-plugin-cc-patched

  4. unitea1992 commented on Oct 10, 2026

    @unitea1992

    Another data point from Linux (codex-cli 0.162.1, plugin v1.0.6), with sandbox_mode = "danger-full-access" and approval_policy = "never" in ~/.codex/config.toml:

    • A codex:codex-rescue task could not create a git worktree (.git/refs/heads/...lock: Read-only file system) and could not write its report file outside the repository, because the rescue agent ran it without --write (read-only) and --write would still be workspace-write.
    • I sent thread/start to the app-server with sandbox: null and approvalPolicy: null; the response resolved to dangerFullAccess / never from config.toml. So omitting or nulling both fields is enough to honor the user's config.

    +1 for #508. It would also help if the rescue agent could be told to keep the user's configured sandbox (for example a --sandbox config option), so diagnosis tasks that need to write outside the workspace do not silently fall back to read-only.

  5. blake-tisbury commented on Oct 21, 2026

    @blake-tisbury

    Same on Windows 11 (codex-cli 0.159.2, plugin 1.0.6). Our config.toml has sandbox_mode = "danger-full-access", because the elevated Windows sandbox was too slow on our machine and we turned it off. Every plugin task and review still asked for read-only / workspace-write, went through codex-windows-sandbox-setup.exe, and failed with orchestrator_helper_exit_nonzero before its first command.

    Letting the configured mode win fixed it locally: tasks and reviews start shells again.

    • scripts/lib/codex.mjs: buildThreadParams / buildResumeParams use sandbox: options.sandbox ?? null, and runAppServerReview stops passing sandbox: "read-only".
    • scripts/codex-companion.mjs: the adversarial review and task stop passing sandbox (--write no longer picks a mode).

    A flag or a config key that lets the user's sandbox_mode win (or #145's --full-access) would remove the need to patch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions