use supercode_harness::tools::{BashTool, NetworkPolicy, SandboxPolicy, Tool, ToolContext};
use supercode_harness::{SandboxEnvPolicy, SandboxEscalation};
fn tmp_dir(label: &str) -> std::path::PathBuf {
use std::sync::atomic::{AtomicU64, Ordering};
static N: AtomicU64 = AtomicU64::new(0);
let d = std::env::temp_dir().join(format!(
"sc-sandbox-{label}-{}-{}",
std::process::id(),
N.fetch_add(1, Ordering::SeqCst)
));
std::fs::create_dir_all(&d).unwrap();
d
}
fn outside_workspace_and_temp_dir(label: &str) -> std::path::PathBuf {
use std::sync::atomic::{AtomicU64, Ordering};
static N: AtomicU64 = AtomicU64::new(0);
let home = std::env::var("HOME").unwrap_or_else(|_| "/root".to_string());
let d = std::path::PathBuf::from(home).join(format!(
".sc-sandbox-outside-{label}-{}-{}",
std::process::id(),
N.fetch_add(1, Ordering::SeqCst)
));
std::fs::create_dir_all(&d).expect("HOME must be writable to run this test");
d
}
fn ctx_for(cwd: &std::path::Path, sandbox: SandboxPolicy) -> ToolContext {
let mut ctx = ToolContext::new(cwd);
ctx.sandbox = sandbox;
ctx
}
async fn run_bash(ctx: &ToolContext, command: &str) -> supercode_harness::Result<String> {
BashTool::default()
.execute(serde_json::json!({ "command": command }), ctx)
.await
}
#[tokio::test]
async fn real_landlock_denies_write_outside_workspace_under_workspace_write() {
let cwd = tmp_dir("wsw-inside");
let outside = outside_workspace_and_temp_dir("wsw-outside");
let ctx = ctx_for(&cwd, SandboxPolicy::WorkspaceWrite);
let inside_target = cwd.join("ok.txt");
let out = run_bash(&ctx, &format!("echo hello > {}", inside_target.display()))
.await
.expect("bash tool call itself must not error");
assert!(
out.starts_with("exit code: 0"),
"write INSIDE the workspace must succeed under workspace_write, got: {out}"
);
assert_eq!(
std::fs::read_to_string(&inside_target).unwrap().trim(),
"hello",
"the write must have actually landed on disk"
);
let outside_target = outside.join("pwned.txt");
let out = run_bash(
&ctx,
&format!("echo pwned > {} 2>&1", outside_target.display()),
)
.await
.expect("bash tool call itself must not error (the SHELL fails, not the tool call)");
assert!(
!out.starts_with("exit code: 0"),
"write OUTSIDE the workspace must be denied by the kernel, got: {out}"
);
let lower = out.to_lowercase();
assert!(
lower.contains("permission denied") || lower.contains("operation not permitted"),
"the denial must be a real kernel EPERM (sh's own error text), got: {out}"
);
assert!(
!outside_target.exists(),
"the outside file must never have been created"
);
let _ = std::fs::remove_dir_all(&cwd);
let _ = std::fs::remove_dir_all(&outside);
}
#[tokio::test]
async fn real_landlock_denies_all_writes_under_read_only() {
let cwd = tmp_dir("ro");
std::fs::write(cwd.join("preexisting.txt"), "seed").unwrap();
let ctx = ctx_for(&cwd, SandboxPolicy::ReadOnly);
let target = cwd.join("should-not-exist.txt");
let out = run_bash(&ctx, &format!("echo x > {} 2>&1", target.display()))
.await
.unwrap();
assert!(
!out.starts_with("exit code: 0"),
"a write under read_only, even inside cwd, must be kernel-denied, got: {out}"
);
assert!(!target.exists());
let out = run_bash(
&ctx,
&format!("cat {}", cwd.join("preexisting.txt").display()),
)
.await
.unwrap();
assert!(
out.contains("seed"),
"reads must stay unrestricted under read_only, got: {out}"
);
let _ = std::fs::remove_dir_all(&cwd);
}
#[tokio::test]
async fn confinement_never_touches_the_calling_process() {
let cwd = tmp_dir("child-only-a");
let outside = outside_workspace_and_temp_dir("child-only-b");
let ctx = ctx_for(&cwd, SandboxPolicy::WorkspaceWrite);
let denied_target = outside.join("denied.txt");
let out = run_bash(&ctx, &format!("echo x > {} 2>&1", denied_target.display()))
.await
.unwrap();
assert!(!out.starts_with("exit code: 0"));
let proof_path = outside.join("supercode_itself_can_still_write.txt");
std::fs::write(&proof_path, "supercode session/checkpoint store write").expect(
"the calling process must be completely unaffected by the child's Landlock restriction",
);
assert_eq!(
std::fs::read_to_string(&proof_path).unwrap(),
"supercode session/checkpoint store write"
);
let _ = std::fs::remove_dir_all(&cwd);
let _ = std::fs::remove_dir_all(&outside);
}
#[tokio::test]
async fn danger_full_access_applies_no_confinement() {
let cwd = tmp_dir("dfa-inside");
let outside = tmp_dir("dfa-outside");
let ctx = ctx_for(&cwd, SandboxPolicy::DangerFullAccess);
let outside_target = outside.join("fine.txt");
let out = run_bash(&ctx, &format!("echo ok > {}", outside_target.display()))
.await
.unwrap();
assert!(
out.starts_with("exit code: 0"),
"danger_full_access must not confine anything, got: {out}"
);
assert!(outside_target.exists());
let _ = std::fs::remove_dir_all(&cwd);
let _ = std::fs::remove_dir_all(&outside);
}
#[tokio::test]
async fn explicit_enabled_false_disables_os_confinement_even_for_a_confining_tier() {
let cwd = tmp_dir("disabled-inside");
let outside = tmp_dir("disabled-outside");
let mut ctx = ctx_for(&cwd, SandboxPolicy::WorkspaceWrite);
ctx.sandbox_os_enabled = Some(false);
let outside_target = outside.join("fine.txt");
let out = run_bash(&ctx, &format!("echo ok > {}", outside_target.display()))
.await
.unwrap();
assert!(
out.starts_with("exit code: 0"),
"enabled=false must disable OS confinement even for a confining tier, got: {out}"
);
let _ = std::fs::remove_dir_all(&cwd);
let _ = std::fs::remove_dir_all(&outside);
}
fn shell_env_with_secret() -> std::sync::Arc<std::collections::HashMap<String, String>> {
let mut m = std::collections::HashMap::new();
m.insert(
"OPENROUTER_API_KEY".to_string(),
"sk-p5-10-test-secret".to_string(),
);
m.insert("HARMLESS_VAR".to_string(), "still-here".to_string());
std::sync::Arc::new(m)
}
#[tokio::test]
async fn env_policy_inherit_passes_the_secret_through_byte_identical() {
let cwd = tmp_dir("env-inherit");
let mut ctx = ctx_for(&cwd, SandboxPolicy::DangerFullAccess);
ctx.shell_env = Some(shell_env_with_secret());
ctx.sandbox_env_policy = SandboxEnvPolicy::Inherit;
let out = run_bash(&ctx, "echo $OPENROUTER_API_KEY").await.unwrap();
assert!(
out.contains("sk-p5-10-test-secret"),
"Inherit (byte-identical, pre-P5-10 default) must still pass the snapshot through, got: {out}"
);
let _ = std::fs::remove_dir_all(&cwd);
}
#[tokio::test]
async fn env_policy_filtered_strips_the_secret_keeps_the_rest() {
let cwd = tmp_dir("env-filtered");
let mut ctx = ctx_for(&cwd, SandboxPolicy::DangerFullAccess);
ctx.shell_env = Some(shell_env_with_secret());
ctx.sandbox_env_policy = SandboxEnvPolicy::Filtered;
let out = run_bash(&ctx, "echo [$OPENROUTER_API_KEY] [$HARMLESS_VAR]")
.await
.unwrap();
assert!(
!out.contains("sk-p5-10-test-secret"),
"Filtered must strip the secret var, got: {out}"
);
assert!(
out.contains("still-here"),
"Filtered must keep a harmless var, got: {out}"
);
}
#[tokio::test]
async fn env_policy_none_keeps_only_the_minimal_set() {
let cwd = tmp_dir("env-none");
let mut ctx = ctx_for(&cwd, SandboxPolicy::DangerFullAccess);
ctx.shell_env = Some(shell_env_with_secret());
ctx.sandbox_env_policy = SandboxEnvPolicy::None;
let out = run_bash(&ctx, "echo [$OPENROUTER_API_KEY] [$HARMLESS_VAR]")
.await
.unwrap();
assert!(!out.contains("sk-p5-10-test-secret"));
assert!(!out.contains("still-here"));
}
#[tokio::test]
async fn network_domain_rules_gap_never_blocks_the_call() {
let cwd = tmp_dir("net-domain-gap");
let mut ctx = ctx_for(&cwd, SandboxPolicy::DangerFullAccess);
ctx.network_policy = Some(NetworkPolicy {
enabled: true,
allow_domains: vec!["example.com".to_string()],
deny_domains: vec![],
});
let out = run_bash(&ctx, "echo still-runs").await.unwrap();
assert!(
out.starts_with("exit code: 0") && out.contains("still-runs"),
"an unenforceable network policy must warn, never refuse the call, got: {out}"
);
let _ = std::fs::remove_dir_all(&cwd);
}
struct FixedApproval(supercode_harness::permissions::ApprovalOutcome);
impl supercode_harness::permissions::PermissionsApprovalHandler for FixedApproval {
fn ask(
&self,
_req: &supercode_harness::permissions::ApprovalRequest,
) -> supercode_harness::permissions::ApprovalOutcome {
self.0
}
}
#[tokio::test]
async fn escalation_ask_is_not_consulted_when_confinement_is_actually_available() {
let cwd = tmp_dir("ask-not-consulted");
let mut ctx = ctx_for(&cwd, SandboxPolicy::WorkspaceWrite);
ctx.sandbox_escalation = SandboxEscalation::Ask;
ctx.sandbox_approval_handler = Some(supercode_harness::sandbox::SandboxApprovalHandler(
std::sync::Arc::new(FixedApproval(
supercode_harness::permissions::ApprovalOutcome::Deny,
)),
));
let inside = cwd.join("ok.txt");
let out = run_bash(&ctx, &format!("echo hi > {}", inside.display()))
.await
.unwrap();
assert!(
out.starts_with("exit code: 0"),
"confinement being AVAILABLE must short-circuit escalation entirely, got: {out}"
);
let _ = std::fs::remove_dir_all(&cwd);
}