mirror of
https://github.com/openai/codex.git
synced 2026-11-02 19:43:24 +00:00
Skip missing paths in filesystem sandbox entries (#34598)
## Why Default read-only protections for project metadata should apply when paths such as `.git`, `.agents`, and `.codex` exist, without causing sandbox setup to materialize missing paths as ACL targets. ## What changed - Add an optional `missing_path_behavior` to filesystem sandbox entries and mark default project-metadata protections with `skip`. - Preserve the behavior through permission transforms and exec/MCP protocol serialization while keeping existing path wire variants stable. - Ignore skip-missing entries when projecting configuration or Windows sandbox overrides, while retaining explicit metadata carveouts. ## Testing - Cover protocol round trips for path and special-path entries. - Verify default metadata protections and Windows explicit carveout handling. GitOrigin-RevId: 6df13dadacdd131c44aab9f15a967c81051355c1
This commit is contained in:
@@ -394,14 +394,14 @@ fn create_filesystem_args(
|
||||
.iter()
|
||||
.filter(|entry| entry.access == FileSystemAccessMode::Read)
|
||||
.filter_map(|entry| {
|
||||
let FileSystemPath::Special {
|
||||
value:
|
||||
FileSystemSpecialPath::ProjectRoots {
|
||||
subpath: Some(subpath),
|
||||
},
|
||||
} = &entry.path
|
||||
else {
|
||||
return None;
|
||||
let subpath = match &entry.path {
|
||||
FileSystemPath::Special {
|
||||
value:
|
||||
FileSystemSpecialPath::ProjectRoots {
|
||||
subpath: Some(subpath),
|
||||
},
|
||||
} => subpath,
|
||||
_ => return None,
|
||||
};
|
||||
// Automatic repo-metadata read masks are skipped here so the
|
||||
// metadata handling below can apply the root-scoped
|
||||
@@ -1348,6 +1348,7 @@ mod tests {
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::GlobPattern { pattern },
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1426,6 +1427,7 @@ mod tests {
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
unreadable_glob_entry(format!("{}/**/*.env", temp_dir.path().display())),
|
||||
]);
|
||||
@@ -1470,12 +1472,14 @@ mod tests {
|
||||
value: FileSystemSpecialPath::Minimal,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::project_roots(/*subpath*/ None),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -1544,10 +1548,12 @@ mod tests {
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path { path: link_root },
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path { path: link_blocked },
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -1594,6 +1600,7 @@ mod tests {
|
||||
path: logical_memories_root,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
}]);
|
||||
|
||||
let args =
|
||||
@@ -1633,6 +1640,7 @@ mod tests {
|
||||
let policy = FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path { path: root },
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
}]);
|
||||
|
||||
let err =
|
||||
@@ -1669,10 +1677,12 @@ mod tests {
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path { path: link_root },
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path { path: link_private },
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -1704,10 +1714,12 @@ mod tests {
|
||||
path: workspace_root,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path { path: blocked_root },
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -1750,6 +1762,7 @@ mod tests {
|
||||
path: workspace_root,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
}]);
|
||||
|
||||
let args =
|
||||
@@ -1799,6 +1812,7 @@ mod tests {
|
||||
path: workspace_root,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
}]);
|
||||
|
||||
let args = create_filesystem_args(&policy, &workspace, NO_UNREADABLE_GLOB_SCAN_MAX_DEPTH)
|
||||
@@ -1845,6 +1859,7 @@ mod tests {
|
||||
path: link_workspace_root,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
}]);
|
||||
|
||||
let args =
|
||||
@@ -1914,30 +1929,35 @@ mod tests {
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::project_roots(/*subpath*/ None),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::project_roots(Some(".git".into())),
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::project_roots(Some(".agents".into())),
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::project_roots(Some(".codex".into())),
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -1972,24 +1992,28 @@ mod tests {
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::project_roots(/*subpath*/ None),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::project_roots(Some(".vscode".into())),
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
value: FileSystemSpecialPath::project_roots(Some(".secrets".into())),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -2105,6 +2129,7 @@ mod tests {
|
||||
.expect("absolute readable root"),
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
}]);
|
||||
|
||||
let args =
|
||||
@@ -2132,6 +2157,7 @@ mod tests {
|
||||
value: FileSystemSpecialPath::Minimal,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
}]);
|
||||
|
||||
let args =
|
||||
@@ -2169,10 +2195,12 @@ mod tests {
|
||||
path: writable_root,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path { path: blocked },
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -2242,16 +2270,19 @@ mod tests {
|
||||
path: writable_root,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path { path: docs.clone() },
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: docs_public.clone(),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -2294,18 +2325,21 @@ mod tests {
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: blocked.clone(),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: allowed.clone(),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -2363,18 +2397,21 @@ mod tests {
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: blocked.clone(),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: allowed_file.clone(),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -2444,14 +2481,17 @@ mod tests {
|
||||
path: writable_root,
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path { path: blocked },
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path { path: allowed },
|
||||
access: FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -2493,12 +2533,14 @@ mod tests {
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: blocked.clone(),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -2537,12 +2579,14 @@ mod tests {
|
||||
value: FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: blocked_file.clone(),
|
||||
},
|
||||
access: FileSystemAccessMode::Deny,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
|
||||
@@ -455,6 +455,7 @@ fn build_preflight_bwrap_argv(
|
||||
value: FileSystemSpecialPath::Minimal,
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
}]);
|
||||
let preflight_command = vec![resolve_true_command()];
|
||||
build_bwrap_argv(
|
||||
|
||||
@@ -221,10 +221,12 @@ fn split_only_filesystem_policy_requires_direct_runtime_enforcement() {
|
||||
),
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Path { path: docs },
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -245,10 +247,12 @@ fn root_write_read_only_carveout_requires_direct_runtime_enforcement() {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Path { path: docs },
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -566,10 +570,12 @@ fn resolve_permission_profile_preserves_direct_runtime_profile() {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Path { path: docs },
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
@@ -620,10 +626,12 @@ fn legacy_landlock_rejects_split_only_filesystem_policies() {
|
||||
value: codex_protocol::permissions::FileSystemSpecialPath::Root,
|
||||
},
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Read,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
codex_protocol::permissions::FileSystemSandboxEntry {
|
||||
path: codex_protocol::permissions::FileSystemPath::Path { path: docs },
|
||||
access: codex_protocol::permissions::FileSystemAccessMode::Write,
|
||||
missing_path_behavior: None,
|
||||
},
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user