Memory Phase 2 ignores sandbox_mode=danger-full-access and starts nested macOS sandbox-exec
What issue are you seeing?
Memory Phase 1 generates raw memories, but Phase 2/global memory consolidation does not produce updated MEMORY.md / memory_summary.md artifacts.
This occurs when Codex itself is already running in a macOS sandboxed context, and the Phase 2 memory worker then attempts to launch/apply another nested macOS sandbox-exec sandbox.
My Codex config explicitly disables Codex's own sandboxing:
sandbox_mode = "danger-full-access"
approval_policy = "never"
[features]
memories = true
Despite that configuration, the memory-consolidation worker appears to start under a nested macOS sandbox-exec / WorkspaceWrite sandbox instead of honoring the effective danger-full-access sandbox mode.
Phase 1 updates:
$HOME/.codex/memories/raw_memories.md
but Phase 2 does not update:
$HOME/.codex/memories/MEMORY.md
$HOME/.codex/memories/memory_summary.md
The consolidation worker rollout shows sandboxing is active even though user config disables it:
cwd=$HOME/.codex/memories
sandbox_policy=WorkspaceWrite
writable_roots=[$HOME/code/random_repo_im_in]
network_access=false
The downstream failure in this macOS environment is:
sandbox-exec: sandbox_apply: Operation not permitted
Given the active sandbox_mode = "danger-full-access" setting, I would not expect the Phase 2 memory worker to invoke macOS sandbox-exec unless that override is intentional and documented.
What steps can reproduce the bug?
- On macOS, launch Codex in a sandboxed parent context.
For example, reproduce from the Codex desktop app/runtime if that process is already subject to a macOS sandbox, or otherwise launch the parent Codex process under a macOS sandboxed environment.
- Configure Codex with Codex sandboxing disabled:
sandbox_mode = "danger-full-access"
approval_policy = "never"
[features]
memories = true
- Start Codex from a project workspace, for example:
$HOME/code/random_repo_im_in
- Generate enough memory-relevant activity for Phase 1 and Phase 2 memory processing to run.
- Observe that Phase 1 writes:
$HOME/.codex/memories/raw_memories.md
- Observe that Phase 2/global consolidation does not update:
$HOME/.codex/memories/MEMORY.md
$HOME/.codex/memories/memory_summary.md
- Inspect the memory-consolidation worker rollout/session metadata.
Observed worker state:
cwd=$HOME/.codex/memories
sandbox_policy=WorkspaceWrite
writable_roots=[$HOME/code/random_repo_im_in]
network_access=false
- Observe the macOS sandbox failure:
sandbox-exec: sandbox_apply: Operation not permitted
The key reproduction point is that Codex is already running in a macOS sandboxed parent context, and the memory worker still launches with a nested WorkspaceWrite / sandbox-exec sandbox even though the active Codex config requests danger-full-access.
What is the expected behavior?
Codex should honor the configured sandbox mode for internal memory-consolidation workers.
With:
sandbox_mode = "danger-full-access"
the Phase 2/global memory-consolidation worker should not start a nested macOS sandbox-exec / WorkspaceWrite sandbox inside an already sandboxed Codex parent process unless there is a clearly documented, intentional exception.
At minimum, the worker should be able to read and write:
$HOME/.codex/memories
and produce updated:
$HOME/.codex/memories/MEMORY.md
$HOME/.codex/memories/memory_summary.md
If the consolidation worker cannot run because sandbox application fails, Phase 2 should fail/retry the job instead of treating the worker's final response as successful consolidation.
Additional information
The suspected issue is in the Phase 2 memory-consolidation worker setup:
codex-rs/memories/write/src/phase2.rs
The visible failure is a nested macOS sandbox application failure: Codex is already running in a sandboxed parent context, and the Phase 2 worker then attempts to apply another sandbox-exec sandbox.
sandbox-exec: sandbox_apply: Operation not permitted
The important part is that the user-level Codex config has sandboxing disabled:
sandbox_mode = "danger-full-access"
approval_policy = "never"
but the memory-consolidation worker still appears to force a WorkspaceWrite sandbox:
agent_config.cwd = root.clone();
let writable_roots = vec![root];
let consolidation_sandbox_policy = SandboxPolicy::WorkspaceWrite { ... };
agent_config
.permissions
.set_legacy_sandbox_policy(consolidation_sandbox_policy, agent_config.cwd.as_path())
.ok()?;
That means Phase 2 is not honoring the effective sandbox configuration for the internal worker. On macOS this manifests as a nested sandbox-exec attempt that fails with sandbox_apply: Operation not permitted.
There may also be a related runtime state issue after the workspace-roots changes:
c25d905f61ca96ed575cd24e82fc4295465c66d0
permissions: support workspace roots in profiles (#22610)
8a5306ff88b868685ca76cfd5cdda42dca637d10
app-server: use permission ids and runtime workspace roots (#22611)
After #22611, new sessions are wired from:
workspace_roots: config.workspace_roots.clone(),
So if Phase 2 does intentionally create a WorkspaceWrite worker, it also needs to keep Config.workspace_roots in sync with the worker's actual memory-root cwd. In the observed rollout, the worker has:
cwd=$HOME/.codex/memories
writable_roots=[$HOME/code/random_repo_im_in]
which suggests stale parent-project workspace roots are leaking into the worker session.
However, that stale-root behavior is secondary to the main bug report: with sandbox_mode = "danger-full-access", the memory worker should not be starting a nested macOS sandbox in the first place unless that behavior is explicitly intended and made compatible with this environment.
7 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
This is not a duplicate of those issues.
I reproduced this locally and have a proposed patch pushed here:
Root cause I found:
phase2::agent::get_configalways replaced the memory-consolidation worker sandbox withWorkspaceWrite, even when the effective parent config wasdanger-full-access.Permissionsobject directly, which leftConfig.workspace_rootscarrying the parent project roots while the workercwdwas$CODEX_HOME/memories.The patch changes Phase 2 worker config so:
DangerFullAccessstaysDangerFullAccess, avoiding a nested Codex-managed sandbox.ExternalSandboxstaysExternalSandbox, preserving the external sandbox/network state.ReadOnly/WorkspaceWritestill get the locked-down no-network memory-rootWorkspaceWritepolicy.Config::set_legacy_sandbox_policy, keepingConfig.workspace_rootssynchronized with the worker memory-rootcwd.Validation:
DangerFullAccess,ExternalSandbox, and workspace-root rebinding.just fmt.just test -p codex-memories-write.git diff --check.I tried opening a PR, but GitHub currently blocks non-collaborators from creating PRs against this repository. If a maintainer wants to invite a PR or cherry-pick the commit, the branch above should be ready.
Hi,
Checking! Thanks :)
Ok, after digging a bit more, the issue is slightly different from what I initially thought but the sympoms are real
I'll land a fix for this
Thank you!!
(I will be curious to see exactly what’s going wrong when the diff lands :) - gotta see where the agents went astray)