cargo fmt

This commit is contained in:
elipeter 2026-05-21 14:35:42 -05:00
parent bec7bbf96c
commit 3a35cd6c8f
294 changed files with 6809 additions and 3911 deletions

View file

@ -182,30 +182,28 @@ pub fn pick_chain_cap(bits: u32) -> Option<Cap> {
while remaining != 0 {
let bit = 1u32 << remaining.trailing_zeros();
if let Some(cap) = Cap::from_bits(bit)
&& lookup_impact(cap, None).is_some() {
return Some(cap);
}
&& lookup_impact(cap, None).is_some()
{
return Some(cap);
}
remaining &= !bit;
}
lowest_cap(bits)
}
fn locate_reach(
loc: &SourceLocation,
surface: &SurfaceMap,
reach: Option<&FileReachMap>,
) -> Reach {
fn locate_reach(loc: &SourceLocation, surface: &SurfaceMap, reach: Option<&FileReachMap>) -> Reach {
// Pass 1: file-local match (legacy behaviour, always applies).
for node in &surface.nodes {
if let SurfaceNode::EntryPoint(ep) = node
&& ep.handler_location.file == loc.file {
return Reach::Reachable {
location: ep.location.clone(),
method: ep.method,
route: ep.route.clone(),
auth_required: ep.auth_required,
};
}
&& ep.handler_location.file == loc.file
{
return Reach::Reachable {
location: ep.location.clone(),
method: ep.method,
route: ep.route.clone(),
auth_required: ep.auth_required,
};
}
}
// Pass 2: transitive caller match via the call graph. Only fires
// when `reach` is supplied — keeps the legacy file-local behaviour
@ -213,14 +211,15 @@ fn locate_reach(
if let Some(reach) = reach {
for node in &surface.nodes {
if let SurfaceNode::EntryPoint(ep) = node
&& reach.reaches(&ep.handler_location.file, &loc.file) {
return Reach::Reachable {
location: ep.location.clone(),
method: ep.method,
route: ep.route.clone(),
auth_required: ep.auth_required,
};
}
&& reach.reaches(&ep.handler_location.file, &loc.file)
{
return Reach::Reachable {
location: ep.location.clone(),
method: ep.method,
route: ep.route.clone(),
auth_required: ep.auth_required,
};
}
}
}
Reach::Unreachable

View file

@ -69,7 +69,10 @@ impl Feasibility {
/// in the doc's table can fire. Phase 25's scoring pass uses this
/// flavour.
pub fn for_finding(diag: &Diag) -> Feasibility {
let verdict = diag.evidence.as_ref().and_then(|e| e.dynamic_verdict.as_ref());
let verdict = diag
.evidence
.as_ref()
.and_then(|e| e.dynamic_verdict.as_ref());
Self::bucket_from_verdict(verdict, diag.confidence)
}
@ -82,9 +85,7 @@ impl Feasibility {
) -> Feasibility {
match verdict.map(|v| v.status) {
Some(VerifyStatus::Confirmed) => Feasibility::Confirmed,
Some(VerifyStatus::Inconclusive)
if static_confidence == Some(Confidence::High) =>
{
Some(VerifyStatus::Inconclusive) if static_confidence == Some(Confidence::High) => {
Feasibility::InconclusiveHighConf
}
_ => Feasibility::Unverified,

View file

@ -210,23 +210,14 @@ mod tests {
#[test]
fn stable_hash_changes_with_member_order() {
let a = ChainFinding::compute_stable_hash(
&[member(1), member(2)],
ImpactCategory::Rce,
);
let b = ChainFinding::compute_stable_hash(
&[member(2), member(1)],
ImpactCategory::Rce,
);
let a = ChainFinding::compute_stable_hash(&[member(1), member(2)], ImpactCategory::Rce);
let b = ChainFinding::compute_stable_hash(&[member(2), member(1)], ImpactCategory::Rce);
assert_ne!(a, b);
}
#[test]
fn stable_hash_changes_with_impact() {
let a = ChainFinding::compute_stable_hash(
&[member(1), member(2)],
ImpactCategory::Rce,
);
let a = ChainFinding::compute_stable_hash(&[member(1), member(2)], ImpactCategory::Rce);
let b = ChainFinding::compute_stable_hash(
&[member(1), member(2)],
ImpactCategory::BrowserToLocalRce,

View file

@ -250,9 +250,10 @@ pub fn lookup_impact(source: Cap, adjacent: Option<Cap>) -> Option<ImpactCategor
// try the standalone rule on adjacent_cap so a CODE_EXEC + UNRELATED
// pair still reaches `Rce`.
if let Some(adj) = adjacent
&& let Some(cat) = standalone_lookup(adj) {
return Some(cat);
}
&& let Some(cat) = standalone_lookup(adj)
{
return Some(cat);
}
None
}

View file

@ -264,8 +264,8 @@ impl CompositeReverifier for DefaultCompositeReverifier {
if result.cache_hit {
cache_hits += 1;
}
total_build_ms = total_build_ms
.saturating_add(result.duration.as_millis());
total_build_ms =
total_build_ms.saturating_add(result.duration.as_millis());
built_steps.push((built_harness.workdir, spec));
}
Err(_) => build_errors += 1,
@ -400,7 +400,11 @@ fn run_chain_steps(
let mut prev_output: Option<Vec<u8>> = None;
let last_idx = built_steps.len().saturating_sub(1);
for (idx, (workdir, spec)) in built_steps.iter().enumerate() {
let step_terminal = if idx == last_idx { Some(terminal) } else { None };
let step_terminal = if idx == last_idx {
Some(terminal)
} else {
None
};
let step = lang::compose_chain_step(spec.lang, prev_output.as_deref(), step_terminal);
let step_path = workdir.join(&step.filename);
@ -459,7 +463,13 @@ fn run_chain_steps(
}
}
}
(steps_run, sandbox_errors, steps_timeout, nonzero_exits, final_sink_hit)
(
steps_run,
sandbox_errors,
steps_timeout,
nonzero_exits,
final_sink_hit,
)
}
/// Phase 26 — Track G.3: drive composite dynamic re-verification for
@ -472,7 +482,13 @@ pub fn reverify_chain(
surface: &SurfaceMap,
opts: &VerifyOptions,
) -> ChainReverifyResult {
reverify_chain_with(chain, member_diags, surface, opts, &DefaultCompositeReverifier)
reverify_chain_with(
chain,
member_diags,
surface,
opts,
&DefaultCompositeReverifier,
)
}
/// Inject-the-reverifier flavour of [`reverify_chain`].
@ -630,7 +646,10 @@ mod tests {
assert!(!result.was_downgraded());
assert_eq!(result.severity_after, ChainSeverity::Critical);
assert_eq!(chain.severity, ChainSeverity::Critical);
assert_eq!(chain.dynamic_verdict.as_ref().unwrap().status, VerifyStatus::Confirmed);
assert_eq!(
chain.dynamic_verdict.as_ref().unwrap().status,
VerifyStatus::Confirmed
);
assert!(chain.reverify_reason.is_none());
}
@ -690,7 +709,10 @@ mod tests {
);
assert!(results.is_empty());
for c in &chains {
assert!(c.dynamic_verdict.is_none(), "no verdict attached when top_n=0");
assert!(
c.dynamic_verdict.is_none(),
"no verdict attached when top_n=0"
);
}
}

View file

@ -178,8 +178,13 @@ mod tests {
#[test]
fn category_weights_strictly_ordered() {
assert!(category_weight(ImpactCategory::BrowserToLocalRce) > category_weight(ImpactCategory::Rce));
assert!(category_weight(ImpactCategory::Rce) > category_weight(ImpactCategory::SessionHijack));
assert!(
category_weight(ImpactCategory::BrowserToLocalRce)
> category_weight(ImpactCategory::Rce)
);
assert!(
category_weight(ImpactCategory::Rce) > category_weight(ImpactCategory::SessionHijack)
);
assert!(
category_weight(ImpactCategory::SessionHijack)
> category_weight(ImpactCategory::InternalNetworkAccess)

View file

@ -120,8 +120,16 @@ pub fn find_chains_with_reach(
.filter(|e| edge_reaches_entry(e, entry, reach))
.collect();
candidates.sort_by(|a, b| {
(a.finding.stable_hash, &a.finding.rule_id, &a.finding.location)
.cmp(&(b.finding.stable_hash, &b.finding.rule_id, &b.finding.location))
(
a.finding.stable_hash,
&a.finding.rule_id,
&a.finding.location,
)
.cmp(&(
b.finding.stable_hash,
&b.finding.rule_id,
&b.finding.location,
))
});
for sink in &sinks {
// Scope candidates to the sink: same-file match (legacy),
@ -139,13 +147,9 @@ pub fn find_chains_with_reach(
})
.copied()
.collect();
if let Some(chain) = compose_chain(
entry,
sink,
&scoped,
cfg.max_depth,
local_listener_present,
) && chain.score >= cfg.min_score
if let Some(chain) =
compose_chain(entry, sink, &scoped, cfg.max_depth, local_listener_present)
&& chain.score >= cfg.min_score
{
chains.push(chain);
}
@ -201,15 +205,9 @@ fn is_loopback_label(s: &str) -> bool {
|| lower.contains("://localhost")
}
fn edge_reaches_entry(
edge: &ChainEdge,
entry: &EntryPoint,
reach: Option<&FileReachMap>,
) -> bool {
fn edge_reaches_entry(edge: &ChainEdge, entry: &EntryPoint, reach: Option<&FileReachMap>) -> bool {
let route_method_match = match &edge.reach {
Reach::Reachable { route, method, .. } => {
*route == entry.route && *method == entry.method
}
Reach::Reachable { route, method, .. } => *route == entry.route && *method == entry.method,
Reach::Unreachable => return false,
};
if !route_method_match {
@ -265,8 +263,7 @@ fn compose_chain(
let bound = scoped.len().min(max_depth);
let path: Vec<&ChainEdge> = scoped[..bound].to_vec();
let sink_cap = sole_cap(sink.cap_bits)?;
let (impact, member_impacts) =
resolve_impact(&path, sink_cap, entry, local_listener_present)?;
let (impact, member_impacts) = resolve_impact(&path, sink_cap, entry, local_listener_present)?;
let mut chain = build_chain(entry, sink, &path, impact, &member_impacts);
// SSRF + LocalListener refinement (Phase 24 deferred close): when
// the implied impact is `InternalNetworkAccess` AND the SurfaceMap
@ -394,9 +391,7 @@ fn build_chain(
/// member edge has `Feasibility::Confirmed` the composite verdict
/// inherits that confirmation; otherwise `None` (Phase 26 will run a
/// real composite re-verification pass).
fn composite_dynamic_verdict(
_path: &[ChainEdge],
) -> Option<crate::evidence::VerifyResult> {
fn composite_dynamic_verdict(_path: &[ChainEdge]) -> Option<crate::evidence::VerifyResult> {
None
}
@ -649,7 +644,9 @@ mod tests {
)
};
let mut surface_no_listener = SurfaceMap::new();
surface_no_listener.nodes.push(entry("app.py", "/fetch", false));
surface_no_listener
.nodes
.push(entry("app.py", "/fetch", false));
surface_no_listener
.nodes
.push(sink("app.py", 20, "requests.get", Cap::SSRF));
@ -662,7 +659,10 @@ mod tests {
},
);
assert_eq!(baseline.len(), 1);
assert_eq!(baseline[0].implied_impact, ImpactCategory::InternalNetworkAccess);
assert_eq!(
baseline[0].implied_impact,
ImpactCategory::InternalNetworkAccess
);
let mut surface_with_listener = surface_no_listener.clone();
surface_with_listener
@ -681,7 +681,10 @@ mod tests {
},
);
assert_eq!(boosted.len(), 1);
assert_eq!(boosted[0].implied_impact, ImpactCategory::InternalNetworkAccess);
assert_eq!(
boosted[0].implied_impact,
ImpactCategory::InternalNetworkAccess
);
let ratio = boosted[0].score / baseline[0].score;
assert!(
(ratio - LOCAL_LISTENER_BOOST).abs() < 1e-9,
@ -693,9 +696,7 @@ mod tests {
fn score_threshold_drops_low_score_chains() {
let mut surface = SurfaceMap::new();
surface.nodes.push(entry("app.py", "/r", false));
surface
.nodes
.push(sink("app.py", 20, "open", Cap::FILE_IO));
surface.nodes.push(sink("app.py", 20, "open", Cap::FILE_IO));
let e = edge_with(
"app.py",
10,
@ -724,12 +725,9 @@ mod tests {
surface.nodes.push(entry("routes.py", "/exec", false));
// Sink lives in a helper file the entry handler transitively
// reaches, not the entry file itself.
surface.nodes.push(sink(
"helper.py",
20,
"os.system",
Cap::CODE_EXEC,
));
surface
.nodes
.push(sink("helper.py", 20, "os.system", Cap::CODE_EXEC));
let e = edge_with(
"routes.py",
10,
@ -798,15 +796,9 @@ mod tests {
surface.nodes.push(entry("a.js", "/run", false));
surface.nodes.push(entry("b.js", "/run", false));
surface.nodes.push(entry("c.py", "/run", false));
surface
.nodes
.push(sink("a.js", 7, "eval", Cap::CODE_EXEC));
surface
.nodes
.push(sink("b.js", 7, "eval", Cap::CODE_EXEC));
surface
.nodes
.push(sink("c.py", 7, "eval", Cap::CODE_EXEC));
surface.nodes.push(sink("a.js", 7, "eval", Cap::CODE_EXEC));
surface.nodes.push(sink("b.js", 7, "eval", Cap::CODE_EXEC));
surface.nodes.push(sink("c.py", 7, "eval", Cap::CODE_EXEC));
let edges = vec![
edge_with(
"a.js",
@ -845,7 +837,11 @@ mod tests {
let mut hashes: Vec<u64> = chains.iter().map(|c| c.stable_hash).collect();
hashes.sort();
hashes.dedup();
assert_eq!(hashes.len(), 3, "surviving chains must have distinct hashes");
assert_eq!(
hashes.len(),
3,
"surviving chains must have distinct hashes"
);
}
/// File-affinity gate on `edge_reaches_entry`: an entry only
@ -858,12 +854,8 @@ mod tests {
let mut surface = SurfaceMap::new();
surface.nodes.push(entry("a.js", "/run", false));
surface.nodes.push(entry("b.js", "/run", false));
surface
.nodes
.push(sink("a.js", 7, "eval", Cap::CODE_EXEC));
surface
.nodes
.push(sink("b.js", 7, "eval", Cap::CODE_EXEC));
surface.nodes.push(sink("a.js", 7, "eval", Cap::CODE_EXEC));
surface.nodes.push(sink("b.js", 7, "eval", Cap::CODE_EXEC));
// Single finding lives in a.js only. Both entries match
// route+method but only entry@a.js shares the file.
let edges = vec![edge_with(