[pitboss] sweep after phase 19: 3 deferred items resolved

This commit is contained in:
pitboss 2026-05-15 11:28:47 -05:00
parent 7ca0c053f5
commit 1d9b4c688f
12 changed files with 204 additions and 180 deletions

View file

@ -36,6 +36,7 @@ fn crashed_outcome() -> SandboxOutcome {
oob_callback_seen: false,
sink_hit: false,
duration: Duration::from_millis(1),
hardening_outcome: None,
}
}
@ -48,6 +49,7 @@ fn clean_outcome() -> SandboxOutcome {
oob_callback_seen: false,
sink_hit: false,
duration: Duration::from_millis(1),
hardening_outcome: None,
}
}

View file

@ -37,6 +37,7 @@ fn dummy_outcome() -> nyx_scanner::dynamic::sandbox::SandboxOutcome {
oob_callback_seen: false,
sink_hit: true,
duration: Duration::from_millis(1),
hardening_outcome: None,
}
}

View file

@ -47,6 +47,7 @@ mod repro_determinism_tests {
oob_callback_seen: false,
sink_hit: true,
duration: Duration::from_millis(150),
hardening_outcome: None,
}
}

View file

@ -21,14 +21,22 @@ mod hardening_tests {
use std::time::Duration;
use nyx_scanner::dynamic::harness::BuiltHarness;
use nyx_scanner::dynamic::sandbox::process_linux::{
last_hardening_outcome, reset_last_hardening_outcome, HardeningLevel, PrimitiveStatus,
};
use nyx_scanner::dynamic::sandbox::process_linux::{HardeningLevel, PrimitiveStatus};
use nyx_scanner::dynamic::sandbox::seccomp;
use nyx_scanner::dynamic::sandbox::{
self, ProcessHardeningProfile, SandboxBackend, SandboxOptions,
self, HardeningRecord, ProcessHardeningProfile, SandboxBackend, SandboxOptions,
};
fn linux_outcome(out: &sandbox::SandboxOutcome)
-> Option<nyx_scanner::dynamic::sandbox::process_linux::HardeningOutcome>
{
match out.hardening_outcome.as_ref()? {
HardeningRecord::Linux(o) => Some(*o),
#[allow(unreachable_patterns)]
_ => None,
}
}
// ── Probe build ───────────────────────────────────────────────────────────
/// Path to the freshly-built probe binary, shared across every test.
@ -161,7 +169,6 @@ mod hardening_tests {
let tmp = workdir();
let harness = build_harness_with_probe(tmp.path(), &[]);
let opts = strict_opts();
reset_last_hardening_outcome();
let result = sandbox::run(&harness, b"", &opts).expect("sandbox::run");
let stdout = stdout_string(&result);
eprintln!("probe stdout under strict:\n{stdout}");
@ -260,10 +267,9 @@ mod hardening_tests {
let tmp = workdir();
let harness = build_harness_with_probe(tmp.path(), &[]);
let opts = strict_opts();
reset_last_hardening_outcome();
let result = sandbox::run(&harness, b"", &opts).expect("sandbox::run");
let stdout = stdout_string(&result);
let outcome = last_hardening_outcome().expect("hardening outcome recorded");
let outcome = linux_outcome(&result).expect("hardening outcome recorded");
// Parent's user-ns inode for comparison.
let parent_user_ns =
@ -310,10 +316,9 @@ mod hardening_tests {
let tmp = workdir();
let harness = build_harness_with_probe(tmp.path(), &[]);
let opts = strict_opts();
reset_last_hardening_outcome();
let result = sandbox::run(&harness, b"", &opts).expect("sandbox::run");
let stdout = stdout_string(&result);
let outcome = last_hardening_outcome().expect("hardening outcome recorded");
let outcome = linux_outcome(&result).expect("hardening outcome recorded");
match outcome.chroot {
PrimitiveStatus::Applied => {
@ -349,10 +354,9 @@ mod hardening_tests {
let tmp = workdir();
let harness = build_harness_with_probe(tmp.path(), &["traverse"]);
let opts = strict_opts();
reset_last_hardening_outcome();
let result = sandbox::run(&harness, b"", &opts).expect("sandbox::run");
let stdout = stdout_string(&result);
let outcome = last_hardening_outcome().expect("hardening outcome recorded");
let outcome = linux_outcome(&result).expect("hardening outcome recorded");
if matches!(outcome.chroot, PrimitiveStatus::Applied) {
// NotConfirmed shape: the verifier maps a non-zero exit + no
@ -390,10 +394,9 @@ mod hardening_tests {
let tmp = workdir();
let harness = build_harness_with_probe(tmp.path(), &[]);
let opts = strict_opts();
reset_last_hardening_outcome();
let result = sandbox::run(&harness, b"", &opts).expect("sandbox::run");
let stdout = stdout_string(&result);
let outcome = last_hardening_outcome().expect("hardening outcome recorded");
let outcome = linux_outcome(&result).expect("hardening outcome recorded");
match outcome.seccomp {
PrimitiveStatus::Applied => {
@ -422,10 +425,9 @@ mod hardening_tests {
let tmp = workdir();
let harness = build_harness_with_probe(tmp.path(), &[]);
let opts = standard_opts();
reset_last_hardening_outcome();
let result = sandbox::run(&harness, b"", &opts).expect("sandbox::run");
let stdout = stdout_string(&result);
let outcome = last_hardening_outcome().expect("hardening outcome recorded");
let outcome = linux_outcome(&result).expect("hardening outcome recorded");
assert_eq!(outcome.level(), HardeningLevel::Baseline);
assert!(matches!(outcome.no_new_privs, PrimitiveStatus::Applied));

View file

@ -21,13 +21,22 @@ mod hardening_tests {
use nyx_scanner::dynamic::harness::BuiltHarness;
use nyx_scanner::dynamic::sandbox::process_macos::{
last_hardening_outcome, profile_for_caps, reset_last_hardening_outcome,
sandbox_exec_available, HardeningLevel, SANDBOX_EXEC_BIN_ENV,
profile_for_caps, sandbox_exec_available, HardeningLevel, SANDBOX_EXEC_BIN_ENV,
};
use nyx_scanner::dynamic::sandbox::{
self, ProcessHardeningProfile, SandboxBackend, SandboxOptions,
self, HardeningRecord, ProcessHardeningProfile, SandboxBackend, SandboxOptions,
};
fn macos_outcome(out: &sandbox::SandboxOutcome)
-> Option<&nyx_scanner::dynamic::sandbox::process_macos::HardeningOutcome>
{
match out.hardening_outcome.as_ref()? {
HardeningRecord::Macos(o) => Some(o),
#[allow(unreachable_patterns)]
_ => None,
}
}
// ── Probe source + harness helpers ────────────────────────────────────────
/// Python source that tries to read `/etc/passwd`. Exits 0 when the
@ -145,11 +154,10 @@ except Exception as exc:
let tmp = workdir();
let harness = build_harness(tmp.path());
let opts = strict_opts(FILE_IO);
reset_last_hardening_outcome();
let result = sandbox::run(&harness, b"", &opts).expect("sandbox::run");
let stdout = stdout_string(&result);
eprintln!("stdout under path_traversal:\n{stdout}");
let outcome = last_hardening_outcome().expect("hardening outcome recorded");
let outcome = macos_outcome(&result).expect("hardening outcome recorded");
assert_eq!(outcome.level, HardeningLevel::Sandboxed);
assert_eq!(outcome.profile, "path_traversal");
assert!(
@ -173,14 +181,16 @@ except Exception as exc:
let tmp = workdir();
let harness = build_harness(tmp.path());
let opts = standard_opts();
reset_last_hardening_outcome();
let result = sandbox::run(&harness, b"", &opts).expect("sandbox::run");
let stdout = stdout_string(&result);
eprintln!("stdout under standard:\n{stdout}");
// Standard profile means the macOS wrap was never attempted; the
// outcome registry stays at `None` (no prior strict run in this
// test) or carries the prior strict run's outcome. We don't
// assert on the registry — we assert on the probe's exit.
// Standard profile means the macOS wrap was never attempted —
// `hardening_outcome` stays `None` because `wrap_plan` was not
// called. Assert on the probe's marker only.
assert!(
result.hardening_outcome.is_none(),
"standard profile should not produce a hardening outcome",
);
assert!(
stdout.contains("escape:escaped") || stdout.contains("escape:blocked"),
"probe should at least print its marker; stdout:\n{stdout}"
@ -188,7 +198,7 @@ except Exception as exc:
}
/// When `sandbox-exec` is unavailable the wrap is a no-op and the
/// outcome registry records `Trusted`. Tests force the missing
/// returned outcome records `Trusted`. Tests force the missing
/// binary path via the [`SANDBOX_EXEC_BIN_ENV`] override.
#[test]
fn sandbox_exec_missing_records_trusted_outcome() {
@ -197,14 +207,12 @@ except Exception as exc:
let tmp = workdir();
let harness = build_harness(tmp.path());
let opts = strict_opts(FILE_IO);
reset_last_hardening_outcome();
let result = sandbox::run(&harness, b"", &opts).expect("sandbox::run");
let stdout = stdout_string(&result);
let outcome = last_hardening_outcome().expect("hardening outcome recorded");
let outcome = macos_outcome(&result).expect("hardening outcome recorded");
assert_eq!(outcome.level, HardeningLevel::Trusted);
eprintln!("stdout when sandbox-exec missing:\n{stdout}");
unsafe { std::env::remove_var(SANDBOX_EXEC_BIN_ENV) };
let _ = result;
}
/// Phase 18 acceptance (b): when sandbox-exec is missing the

View file

@ -64,6 +64,7 @@ fn empty_outcome() -> SandboxOutcome {
oob_callback_seen: false,
sink_hit: true,
duration: Duration::from_millis(1),
hardening_outcome: None,
}
}