[pitboss] phase 08: Track J.6 + Track L.6 — HEADER_INJECTION corpus + every HTTP framework

This commit is contained in:
pitboss 2026-05-18 01:08:32 -05:00
parent 59d627cb22
commit e0e49f65d3
45 changed files with 2552 additions and 41 deletions

View file

@ -111,7 +111,7 @@ impl ProbeArg {
/// [`crate::dynamic::oracle::Oracle::SinkCrash`] variant ignores anything
/// other than `Crash { signal }`, so a process-level abort outside the
/// sink no longer satisfies the oracle.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(tag = "kind")]
pub enum ProbeKind {
/// Standard sink observation: arguments were captured before the sink
@ -190,6 +190,28 @@ pub enum ProbeKind {
/// payload's XPath expression.
nodes_returned: u32,
},
/// Phase 08 (Track J.6) HTTP-response-header-write observation.
/// Stamped by the per-language harness shim's instrumented header
/// setter (`HttpServletResponse.setHeader`,
/// `flask.Response.headers.__setitem__`, `header(...)`,
/// `Rack::Response#set_header`, `res.setHeader`, `w.Header().Set`,
/// `HeaderMap::insert`). The shim records exactly one probe per
/// `setHeader(name, value)` call carrying the raw bytes the host
/// process emitted — the
/// [`crate::dynamic::oracle::ProbePredicate::HeaderInjected`]
/// predicate scans `value` for an embedded `\r\n` byte pair, which
/// is the signal that the attacker payload split one header into
/// two on the wire.
HeaderEmit {
/// Header name the host attempted to set (e.g. `"Set-Cookie"`,
/// `"Location"`). Echoed verbatim so the predicate can pin
/// per-header expectations without name normalisation.
name: String,
/// Raw header value the host attempted to set. A vulnerable
/// host concatenates attacker bytes into this string without
/// CRLF stripping; a benign host URL-encodes them (`%0d%0a`).
value: String,
},
}
impl Default for ProbeKind {