fix(application,infrastructure): grant /dev/null RO|RW in workspace_exec_sandbox so CLIs can open it O_RDWR — #354 (QA verte)
Cause: the workspace.execTool sandbox only granted the project root plus read-only system roots, so CLI tools like git failed when opening /dev/null with O_RDWR (redirect/exec 3<>/dev/null) inside sandboxed runs. Fix: workspace_exec_sandbox pushes one precise /dev/null PathGrant with RO|RW access; project read effect stays RO|EXEC and no blanket /dev grant is added, so the widening is limited to the null device; GitPlugin untouched. Tests: application asserts the read sandbox keeps project RO|EXEC while granting /dev/null RO|RW (workspace_exec_read_sandbox_grants_dev_null_without_widening_project_access); infrastructure proves the local runner executes exec 3<>/dev/null (local_runner_allows_cli_to_open_dev_null_for_read_and_write). QA verte reconfirmée par Git: cargo test -p application workspace_exec 5/5, -p infrastructure local_runner_allows_cli_to_open_dev_null 1/1, -p infrastructure workspace_tool::tests 5/5, cargo fmt --all --check, git diff --check. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -2443,6 +2443,10 @@ fn workspace_exec_sandbox(
|
||||
abs_root: root.as_str().to_owned(),
|
||||
access: project_access,
|
||||
}];
|
||||
allowed.push(domain::PathGrant {
|
||||
abs_root: "/dev/null".to_owned(),
|
||||
access: domain::PathAccess::RO | domain::PathAccess::RW,
|
||||
});
|
||||
for system_root in ["/bin", "/usr", "/lib", "/lib64", "/etc"] {
|
||||
allowed.push(domain::PathGrant {
|
||||
abs_root: system_root.to_owned(),
|
||||
@ -6063,6 +6067,29 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workspace_exec_read_sandbox_grants_dev_null_without_widening_project_access() {
|
||||
let root = ProjectPath::new("/workspace/example").unwrap();
|
||||
let sandbox = workspace_exec_sandbox(&root, PluginWorkspaceExecEffect::Read);
|
||||
|
||||
assert_eq!(
|
||||
sandbox
|
||||
.allowed
|
||||
.iter()
|
||||
.find(|grant| grant.abs_root == root.as_str())
|
||||
.map(|grant| grant.access),
|
||||
Some(domain::PathAccess::RO | domain::PathAccess::EXEC)
|
||||
);
|
||||
assert_eq!(
|
||||
sandbox
|
||||
.allowed
|
||||
.iter()
|
||||
.find(|grant| grant.abs_root == "/dev/null")
|
||||
.map(|grant| grant.access),
|
||||
Some(domain::PathAccess::RO | domain::PathAccess::RW)
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn workspace_exec_allows_matching_rule_clamps_limits_and_audits_metadata() {
|
||||
let (project_id, tool, runner, audit) = workspace_exec_fixture();
|
||||
|
||||
Reference in New Issue
Block a user