[pitboss/grind] deferred session-0023 (20260517T044708Z-e058)

This commit is contained in:
pitboss 2026-05-17 08:10:32 -05:00
parent f4793b0439
commit b638cade34
8 changed files with 458 additions and 26 deletions

View file

@ -21,7 +21,9 @@ mod hardening_tests {
use nyx_scanner::dynamic::harness::BuiltHarness;
use nyx_scanner::dynamic::sandbox::process_macos::{
profile_for_caps, sandbox_exec_available, HardeningLevel, SANDBOX_EXEC_BIN_ENV,
clear_profile_path_cache_for_tests, profile_for_caps, profile_path,
sandbox_exec_available, HardeningLevel, SANDBOX_EXEC_BIN_ENV, SB_DENY_DEFAULT_ENV,
SB_SEED_DIR_ENV,
};
use nyx_scanner::dynamic::sandbox::{
self, HardeningRecord, ProcessHardeningProfile, SandboxBackend, SandboxOptions,
@ -686,6 +688,98 @@ except Exception as exc:
);
}
/// Phase 18 follow-up smoke test: a synthetic seed under
/// `NYX_SB_SEED_DIR` rewrites the materialised `.sb` profile to
/// `(deny default)` and appends the seed body verbatim. Exercises
/// the splice path through the production [`profile_path`] call
/// site so the env-var → seed-dir → splice → on-disk file flow is
/// validated end-to-end, not just via the unit tests on
/// [`splice_deny_default`].
///
/// Uses the `ssrf` profile because no other test in this file
/// touches it; the cache-clear helper resets state regardless so
/// the assertion holds even if a future test materialises ssrf
/// before this one.
#[test]
fn deny_default_seed_loads_under_strict() {
let seed_dir = tempfile::TempDir::new().expect("seed tempdir");
// The seed body is intentionally over-permissive so the
// /usr/bin/true probe at the end of the test can clear without
// tripping on missing allowances. A real seed generated by
// `tools/sb-trace.sh` would be much tighter (only the rules
// each interpreter cold-start needs).
let seed_body = ";; synthetic seed for end-to-end smoke test\n\
(allow process-fork)\n\
(allow process-exec*)\n\
(allow file-read*)\n\
(allow file-read-metadata)\n\
(allow file-write-data (literal \"/dev/null\"))\n\
(allow mach-lookup)\n\
(allow signal (target self))\n\
(allow sysctl-read)\n\
(allow ipc-posix-shm-read*)\n";
std::fs::write(seed_dir.path().join("ssrf.allow"), seed_body)
.expect("write synthetic seed");
clear_profile_path_cache_for_tests();
unsafe {
std::env::set_var(SB_DENY_DEFAULT_ENV, "1");
std::env::set_var(SB_SEED_DIR_ENV, seed_dir.path());
}
let materialised = profile_path("ssrf").expect("profile materialises");
let body = std::fs::read_to_string(&materialised).expect("read profile body");
unsafe {
std::env::remove_var(SB_DENY_DEFAULT_ENV);
std::env::remove_var(SB_SEED_DIR_ENV);
}
clear_profile_path_cache_for_tests();
assert!(
body.contains("(deny default)"),
"splice should rewrite (allow default) -> (deny default); got: {body}",
);
assert!(
!body.contains("(allow default)"),
"no (allow default) directive should survive the splice; got: {body}",
);
assert!(
body.contains(";; ── deny-default seed (spliced by NYX_SB_DENY_DEFAULT=1) ──"),
"splice banner should appear once; got: {body}",
);
assert!(
body.contains("(allow process-fork)"),
"synthetic seed body should land verbatim; got: {body}",
);
assert!(
body.contains("(allow mach-lookup)"),
"later seed rule should also appear verbatim; got: {body}",
);
// The spliced profile should still parse as valid sandbox-exec
// syntax when the host has the binary on PATH; skip when it
// is missing (stripped CI images) since this assertion is the
// only one that needs the live binary.
if sandbox_exec_available() {
let probe = std::process::Command::new("/usr/bin/sandbox-exec")
.arg("-f")
.arg(&materialised)
.arg("-D")
.arg("WORKDIR=/tmp")
.arg("/usr/bin/true")
.output()
.expect("invoke sandbox-exec on spliced profile");
assert!(
probe.status.success(),
"spliced profile should be valid sandbox-exec syntax; \
status={:?}, stderr={}",
probe.status,
String::from_utf8_lossy(&probe.stderr),
);
}
}
/// Round-trip the portable summary through JSON to lock in the
/// repro-bundle wire shape: `VerifyResult::hardening_outcome` lands
/// on `expected/verdict.json` so the eval-corpus tabulator and any