[pitboss/grind] deferred session-0011 (20260522T043516Z-29b8)

This commit is contained in:
pitboss 2026-05-22 03:30:48 -05:00
parent 189bcb79d4
commit 205fb142c8
12 changed files with 195 additions and 75 deletions

View file

@ -22,7 +22,7 @@ use nyx_scanner::dynamic::corpus::{
use nyx_scanner::dynamic::framework::registry::adapters_for;
use nyx_scanner::dynamic::lang;
use nyx_scanner::dynamic::oracle::{ProbePredicate, oracle_fired};
use nyx_scanner::dynamic::probe::{ProbeKind, ProbeWitness, SinkProbe};
use nyx_scanner::dynamic::probe::{HeaderEmitProtocol, ProbeKind, ProbeWitness, SinkProbe};
use nyx_scanner::dynamic::sandbox::SandboxOutcome;
use nyx_scanner::dynamic::spec::{EntryKind, HarnessSpec, PayloadSlot};
use nyx_scanner::labels::Cap;
@ -158,15 +158,53 @@ fn probe_kind_header_emit_serdes() {
let original = ProbeKind::HeaderEmit {
name: "Set-Cookie".into(),
value: "nyx-session\r\nSet-Cookie: nyx-injected=pwn".into(),
protocol: HeaderEmitProtocol::InProcess,
};
let json = serde_json::to_string(&original).unwrap();
assert!(json.contains("HeaderEmit"));
assert!(json.contains("name"));
assert!(json.contains("value"));
assert!(json.contains("\"protocol\":\"in-process\""));
let parsed: ProbeKind = serde_json::from_str(&json).unwrap();
assert_eq!(parsed, original);
}
#[test]
fn probe_kind_header_emit_serdes_wire_variant() {
let original = ProbeKind::HeaderEmit {
name: "Set-Cookie".into(),
value: "nyx-session\r\nSet-Cookie: nyx-injected=pwn".into(),
protocol: HeaderEmitProtocol::Wire,
};
let json = serde_json::to_string(&original).unwrap();
assert!(json.contains("\"protocol\":\"wire\""));
let parsed: ProbeKind = serde_json::from_str(&json).unwrap();
assert_eq!(parsed, original);
}
#[test]
fn probe_kind_header_emit_deserialises_legacy_records_as_in_process() {
// Probe records emitted before the protocol field existed must
// continue to deserialise via the `#[serde(default)]` hatch so the
// future oracle tightening landing does not need to migrate the
// on-disk channel format.
let legacy_json =
r#"{"kind":"HeaderEmit","name":"Set-Cookie","value":"nyx-session\r\nSet-Cookie: pwn"}"#;
let parsed: ProbeKind = serde_json::from_str(legacy_json).unwrap();
match parsed {
ProbeKind::HeaderEmit {
name,
value,
protocol,
} => {
assert_eq!(name, "Set-Cookie");
assert_eq!(value, "nyx-session\r\nSet-Cookie: pwn");
assert_eq!(protocol, HeaderEmitProtocol::InProcess);
}
other => panic!("expected HeaderEmit, got {other:?}"),
}
}
#[test]
fn header_injected_predicate_fires_on_crlf_value() {
let oracle = Oracle::SinkProbe {
@ -182,6 +220,7 @@ fn header_injected_predicate_fires_on_crlf_value() {
kind: ProbeKind::HeaderEmit {
name: "Set-Cookie".into(),
value: "nyx-session\r\nSet-Cookie: nyx-injected=pwn".into(),
protocol: HeaderEmitProtocol::InProcess,
},
witness: ProbeWitness::empty(),
}];
@ -213,6 +252,7 @@ fn header_injected_predicate_clear_when_value_is_url_encoded() {
kind: ProbeKind::HeaderEmit {
name: "Set-Cookie".into(),
value: "nyx-session%0D%0ASet-Cookie%3A%20nyx-injected%3Dpwn".into(),
protocol: HeaderEmitProtocol::InProcess,
},
witness: ProbeWitness::empty(),
}];
@ -246,6 +286,7 @@ fn header_injected_predicate_clear_on_unrelated_header() {
kind: ProbeKind::HeaderEmit {
name: "X-Trace-Id".into(),
value: "trace\r\nX-Injected: 1".into(),
protocol: HeaderEmitProtocol::InProcess,
},
witness: ProbeWitness::empty(),
}];

View file

@ -254,8 +254,23 @@ fn lang_emitter_dispatches_to_prototype_pollution_harness() {
"{lang:?} harness must install the canary trap on Object.prototype",
);
assert!(
harness.source.contains("nyxDeepMerge"),
"{lang:?} harness must inline the deep-merge sink",
harness.source.contains("require('lodash').merge"),
"{lang:?} harness must route through the real `lodash.merge` (Phase 10 follow-up swap)",
);
assert!(
!harness.source.contains("function nyxDeepMerge"),
"{lang:?} harness must no longer declare the hand-rolled `nyxDeepMerge` shim",
);
assert!(
!harness.source.contains("nyxDeepMerge(target,"),
"{lang:?} harness must no longer call the hand-rolled `nyxDeepMerge` shim",
);
assert!(
harness
.extra_files
.iter()
.any(|(p, c)| p == "package.json" && c.contains("\"lodash\":\"4.17.4\"")),
"{lang:?} harness must publish a `package.json` pinning lodash 4.17.4 (last version before `_.merge` was hardened against `__proto__`); empirical bisect shows 4.17.5+ already filters the key so newer pins flip the vuln fixture to NotConfirmed",
);
assert!(
harness.source.contains("__NYX_SINK_HIT__"),

View file

@ -549,6 +549,17 @@ mod e2e_phase_07 {
.as_ref()
.expect("Confirmed run must carry a DifferentialOutcome");
assert_eq!(diff.verdict, DifferentialVerdict::Confirmed);
let tier_a_marker = b"__NYX_XPATH_TIER_A__";
let saw_tier_a = outcome.attempts.iter().any(|a| {
a.outcome
.stdout
.windows(tier_a_marker.len())
.any(|w| w == tier_a_marker)
});
assert!(
saw_tier_a,
"Python XPath vuln must reach the tier-(a) real-lxml path (stdout marker `__NYX_XPATH_TIER_A__`); the inline `_nyx_xpath_select` fallback was removed and the harness now SKIPs via NYX_IMPORT_ERROR + exit 77 when lxml is unavailable",
);
}
#[test]