Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions codex-rs/core/src/memories/phase2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use crate::memories::storage::sync_rollout_summaries_from_memories;
use codex_config::Constrained;
use codex_features::Feature;
use codex_protocol::ThreadId;
use codex_protocol::permissions::FileSystemSandboxPolicy;
use codex_protocol::permissions::NetworkSandboxPolicy;
use codex_protocol::protocol::AskForApproval;
use codex_protocol::protocol::SandboxPolicy;
use codex_protocol::protocol::SessionSource;
Expand Down Expand Up @@ -296,7 +298,7 @@ mod agent {
let root = memory_root(&config.codex_home);
let mut agent_config = config.as_ref().clone();

agent_config.cwd = root;
agent_config.cwd = root.clone();
// Consolidation threads must never feed back into phase-1 memory generation.
agent_config.memories.generate_memories = false;
// Approval policy
Expand All @@ -307,20 +309,30 @@ mod agent {
let _ = agent_config.features.disable(Feature::MemoryTool);

// Sandbox policy
let writable_roots = vec![agent_config.codex_home.clone()];
// The consolidation agent only needs local codex_home write access and no network.
let writable_roots = vec![root];
// The consolidation agent only needs local memory-root write access and no network.
let consolidation_sandbox_policy = SandboxPolicy::WorkspaceWrite {
writable_roots,
read_only_access: Default::default(),
network_access: false,
exclude_tmpdir_env_var: false,
exclude_slash_tmp: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
};
let consolidation_file_system_sandbox_policy =
FileSystemSandboxPolicy::from_legacy_sandbox_policy(
&consolidation_sandbox_policy,
agent_config.cwd.as_path(),
);
let consolidation_network_sandbox_policy =
NetworkSandboxPolicy::from(&consolidation_sandbox_policy);
agent_config
.permissions
.sandbox_policy
.set(consolidation_sandbox_policy)
.ok()?;
agent_config.permissions.file_system_sandbox_policy =
consolidation_file_system_sandbox_policy;
agent_config.permissions.network_sandbox_policy = consolidation_network_sandbox_policy;

agent_config.model = Some(
config
Expand Down
54 changes: 47 additions & 7 deletions codex-rs/core/src/memories/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,8 @@ mod phase2 {
use codex_config::Constrained;
use codex_login::CodexAuth;
use codex_protocol::ThreadId;
use codex_protocol::permissions::FileSystemSandboxPolicy;
use codex_protocol::permissions::NetworkSandboxPolicy;
use codex_protocol::protocol::AskForApproval;
use codex_protocol::protocol::Op;
use codex_protocol::protocol::SandboxPolicy;
Expand Down Expand Up @@ -473,6 +475,8 @@ mod phase2 {
codex_utils_absolute_path::AbsolutePathBuf::from_absolute_path(codex_home.path())
.expect("codex home is absolute");
config.cwd = config.codex_home.clone();
config.permissions.file_system_sandbox_policy = FileSystemSandboxPolicy::unrestricted();
config.permissions.network_sandbox_policy = NetworkSandboxPolicy::Enabled;
let config = Arc::new(config);

let state_db = codex_state::StateRuntime::init(
Expand Down Expand Up @@ -683,17 +687,53 @@ mod phase2 {
config_snapshot.cwd.as_path(),
memory_root(&harness.config.codex_home).as_path()
);
match config_snapshot.sandbox_policy {
SandboxPolicy::WorkspaceWrite { writable_roots, .. } => {
assert!(
writable_roots
.iter()
.any(|root| root.as_path() == harness.config.codex_home.as_path()),
"consolidation subagent should have codex_home as writable root"
match &config_snapshot.sandbox_policy {
SandboxPolicy::WorkspaceWrite {
writable_roots,
network_access,
..
} => {
assert!(!*network_access);
pretty_assertions::assert_eq!(
writable_roots.as_slice(),
[memory_root(&harness.config.codex_home)],
"consolidation subagent should only be able to write the memory root"
);
}
other => panic!("unexpected sandbox policy: {other:?}"),
}
let turn_context = subagent.codex.session.new_default_turn().await;
pretty_assertions::assert_eq!(
turn_context.file_system_sandbox_policy,
FileSystemSandboxPolicy::from_legacy_sandbox_policy(
&config_snapshot.sandbox_policy,
config_snapshot.cwd.as_path(),
),
"consolidation subagent split filesystem policy should match the memory-root legacy policy"
);
assert!(
turn_context
.file_system_sandbox_policy
.can_write_path_with_cwd(
memory_root(&harness.config.codex_home).as_path(),
config_snapshot.cwd.as_path(),
),
"consolidation subagent should be able to write the memory root"
);
assert!(
!turn_context
.file_system_sandbox_policy
.can_write_path_with_cwd(
harness.config.codex_home.join("config.toml").as_path(),
config_snapshot.cwd.as_path(),
),
"consolidation subagent should not inherit codex_home write access"
);
pretty_assertions::assert_eq!(
turn_context.network_sandbox_policy,
NetworkSandboxPolicy::Restricted,
"consolidation subagent split network policy should preserve no-network sandboxing"
);
subagent.codex.session.ensure_rollout_materialized().await;
subagent
.codex
Expand Down
Loading