use super::tests::live_landlock_available;
use super::*;
#[test]
fn a_tool_on_path_runs_confined_while_one_off_path_and_credentials_stay_denied() {
use std::os::unix::fs::PermissionsExt;
if !live_landlock_available("path-entry-grant") {
return;
}
let _env_lock = crate::runtime_paths::test_env_lock()
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner());
let root = tempfile::TempDir::new().expect("fixture root");
let root_path = root.path().canonicalize().expect("canonical");
let workspace = root_path.join("workspace");
let tool_bin = root_path.join("toolcache/node/24.0.0/x64/bin");
let home = root_path.join("home");
let cargo_bin = home.join(".cargo/bin");
for dir in [&workspace, &tool_bin, &cargo_bin] {
std::fs::create_dir_all(dir).expect("mkdir");
}
let tool = tool_bin.join("harn-path-probe");
let true_bin = std::fs::canonicalize("/bin/true").expect("a host true binary");
std::fs::copy(&true_bin, &tool).expect("stage the probe tool");
std::fs::set_permissions(&tool, std::fs::Permissions::from_mode(0o755)).expect("chmod");
let credentials = home.join(".cargo/credentials.toml");
std::fs::write(&credentials, "token = \"PATH-GRANT-SECRET\"\n").expect("credentials");
let previous_home = std::env::var_os("HOME");
let previous_path = std::env::var_os("PATH");
std::env::set_var("HOME", &home);
let run = |path: String, script: String| {
std::env::set_var("PATH", path);
crate::orchestration::push_execution_policy(CapabilityPolicy {
workspace_roots: vec![workspace.display().to_string()],
sandbox_profile: SandboxProfile::Worktree,
process_sandbox: Box::new(crate::orchestration::ProcessSandboxPolicy {
presets: Some(vec![ProcessSandboxPreset::DeveloperToolchains]),
..Default::default()
}),
..CapabilityPolicy::default()
});
let output = crate::stdlib::sandbox::command_output(
"/bin/sh",
&["-c".to_string(), script],
&crate::stdlib::sandbox::ProcessCommandConfig {
cwd: Some(workspace.clone()),
..Default::default()
},
);
crate::orchestration::pop_execution_policy();
output
};
let on_path = run(
format!("{}:/usr/bin:/bin", tool_bin.display()),
"harn-path-probe && echo PATH-PROBE-RAN".to_string(),
);
let off_path = run(
"/usr/bin:/bin".to_string(),
format!("{} && echo PATH-PROBE-RAN", tool.display()),
);
let credential_read = run(
format!("{}:/usr/bin:/bin", cargo_bin.display()),
format!("cat {}; echo CREDENTIAL-PROBE-RAN", credentials.display()),
);
match previous_path {
Some(value) => std::env::set_var("PATH", value),
None => std::env::remove_var("PATH"),
}
match previous_home {
Some(value) => std::env::set_var("HOME", value),
None => std::env::remove_var("HOME"),
}
let on_path = on_path.expect("the on-PATH spawn is prepared");
assert!(
on_path.status.success()
&& String::from_utf8_lossy(&on_path.stdout).contains("PATH-PROBE-RAN"),
"a tool whose directory is on PATH must run confined: {on_path:?}"
);
match off_path {
Err(error) => assert!(
format!("{error:?}").contains("denied by the OS sandbox"),
"the off-PATH spawn failed for a reason other than the sandbox: {error:?}"
),
Ok(output) => assert!(
!output.status.success()
&& !String::from_utf8_lossy(&output.stdout).contains("PATH-PROBE-RAN"),
"the same file off PATH must stay refused, or case 1 proves nothing: {output:?}"
),
}
match credential_read {
Err(error) => assert!(
format!("{error:?}").contains("is on the credential denylist"),
"the credential read failed for a reason other than the denylist: {error:?}"
),
Ok(output) => {
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("CREDENTIAL-PROBE-RAN") && !stdout.contains("PATH-GRANT-SECRET"),
"~/.cargo/bin on PATH must not open ~/.cargo/credentials.toml: {output:?}"
);
}
}
}