mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-21 20:18:06 +02:00
feat(lint): centralize clippy::collapsible_if allowance in Cargo.toml and remove redundant file-level declarations
This commit is contained in:
parent
1f5777ff11
commit
1ebeb233c4
53 changed files with 851 additions and 212 deletions
|
|
@ -631,6 +631,34 @@ pub fn run_shape_fixture_lang(
|
|||
wrong: None,
|
||||
hardening_outcome: None,
|
||||
},
|
||||
// A sandbox backend the harness requires is not usable on this host
|
||||
// (e.g. compiled C/C++/Go/Rust fixtures need Docker on a machine
|
||||
// without a working process backend, and the daemon is down or
|
||||
// half-up). Project this to `Inconclusive(SandboxError)` rather than
|
||||
// `Unsupported`: `assert_not_confirmed` tolerates `Inconclusive`, so
|
||||
// the direct (non-skip) caller `run_shape_fixture` (used by the Python
|
||||
// suite, which returns a `VerifyResult` and cannot skip) keeps the
|
||||
// same benign verdict it had before this arm existed. The dedicated
|
||||
// `SandboxError` reason is what lets `run_shape_fixture_lang_or_skip`
|
||||
// recognise this specific case and turn it into a clean skip, so a
|
||||
// missing/broken backend never fails a confirm-gate on a host that
|
||||
// simply cannot execute the harness.
|
||||
Err(RunError::Sandbox(
|
||||
nyx_scanner::dynamic::sandbox::SandboxError::BackendUnavailable(_),
|
||||
)) => VerifyResult {
|
||||
finding_id: spec.finding_id.clone(),
|
||||
status: VerifyStatus::Inconclusive,
|
||||
triggered_payload: None,
|
||||
reason: None,
|
||||
inconclusive_reason: Some(InconclusiveReason::SandboxError),
|
||||
detail: Some("sandbox backend unavailable".to_owned()),
|
||||
attempts: vec![],
|
||||
toolchain_match: None,
|
||||
differential: None,
|
||||
replay_stable: None,
|
||||
wrong: None,
|
||||
hardening_outcome: None,
|
||||
},
|
||||
Err(e) => VerifyResult {
|
||||
finding_id: spec.finding_id.clone(),
|
||||
status: VerifyStatus::Inconclusive,
|
||||
|
|
@ -677,7 +705,7 @@ pub fn run_shape_fixture_lang_or_skip(
|
|||
eprintln!("SKIP {lang_dir}/{shape_dir}/{file}: {reason}");
|
||||
return None;
|
||||
}
|
||||
Some(run_shape_fixture_lang(
|
||||
let result = run_shape_fixture_lang(
|
||||
lang,
|
||||
lang_dir,
|
||||
shape_dir,
|
||||
|
|
@ -687,7 +715,23 @@ pub fn run_shape_fixture_lang_or_skip(
|
|||
sink_line,
|
||||
entry_kind,
|
||||
payload_slot,
|
||||
))
|
||||
);
|
||||
// The required sandbox backend is unavailable on this host (probed only at
|
||||
// run time, after the static `check_prerequisites` gate). Treat it as a
|
||||
// structured skip so a missing/broken Docker daemon does not flip an
|
||||
// environment-fragile confirm gate to a hard failure. Only the dedicated
|
||||
// `BackendUnavailable -> Inconclusive(SandboxError)` projection above sets
|
||||
// this reason, so genuine `Inconclusive` verdicts (oracle collisions,
|
||||
// unrelated crashes) and other sandbox errors still flow through to the
|
||||
// assertion. Hosts with a working backend run the fixture to completion,
|
||||
// so coverage is unchanged wherever execution is actually possible.
|
||||
if matches!(result.status, VerifyStatus::Inconclusive)
|
||||
&& result.inconclusive_reason == Some(InconclusiveReason::SandboxError)
|
||||
{
|
||||
eprintln!("SKIP {lang_dir}/{shape_dir}/{file}: sandbox backend unavailable");
|
||||
return None;
|
||||
}
|
||||
Some(result)
|
||||
}
|
||||
|
||||
/// Phase 29 (Track I) — `run_harness_snapshot_lang` with structured
|
||||
|
|
|
|||
19
tests/fixtures/real_world/java/taint/cmdi_ternary_const_safe.expect.json
vendored
Normal file
19
tests/fixtures/real_world/java/taint/cmdi_ternary_const_safe.expect.json
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"description": "Constant-condition ternary (OWASP Benchmark cmdi non-vulnerable shape). `(7*18) + num > 200` with num=106 is 232 > 200 — always true — so `bar` is the constant string and the `: param` arm is statically dead. Extending the ternary-RHS diamond split to Java (src/cfg/mod.rs) routes `bar = cond ? const : param` through a real branch+phi CFG; build_ternary_diamond stamps the CondArith tree so fold_constant_branches prunes the dead tainted arm and neutralises its block, exactly as the if-form does. Result: `r.exec(cmd + bar)` carries no taint. Asserts NO taint finding fires.",
|
||||
"tags": [
|
||||
"taint",
|
||||
"cmdi",
|
||||
"servlet",
|
||||
"runtime",
|
||||
"ternary",
|
||||
"const-fold",
|
||||
"precision"
|
||||
],
|
||||
"modes": [
|
||||
"full"
|
||||
],
|
||||
"strict_unexpected": [
|
||||
"taint-unsanitised-flow"
|
||||
],
|
||||
"expected": []
|
||||
}
|
||||
21
tests/fixtures/real_world/java/taint/cmdi_ternary_const_safe.java
vendored
Normal file
21
tests/fixtures/real_world/java/taint/cmdi_ternary_const_safe.java
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import java.io.*;
|
||||
import javax.servlet.http.*;
|
||||
|
||||
// Constant-condition ternary (OWASP Benchmark cmdi non-vulnerable shape).
|
||||
// `(7*18) + num` is `126 + 106 = 232 > 200` — ALWAYS true — so `bar` is the
|
||||
// constant string and the `: param` arm is statically dead. Routing the Java
|
||||
// ternary through the branch+phi diamond lets `fold_constant_branches` prune
|
||||
// the dead tainted arm exactly as it does for the if-form — NO finding.
|
||||
public class TernaryConstSafe extends HttpServlet {
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
String param = request.getHeader("vector");
|
||||
|
||||
int num = 106;
|
||||
String bar = (7 * 18) + num > 200 ? "This_should_always_happen" : param;
|
||||
|
||||
String cmd = "echo ";
|
||||
Runtime r = Runtime.getRuntime();
|
||||
Process p = r.exec(cmd + bar);
|
||||
}
|
||||
}
|
||||
32
tests/fixtures/real_world/java/taint/cmdi_ternary_param_vuln.expect.json
vendored
Normal file
32
tests/fixtures/real_world/java/taint/cmdi_ternary_param_vuln.expect.json
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"description": "Constant-condition ternary with VULNERABLE polarity. `(500/42) + num > 200` is `11 + 196 = 207 > 200` (integer division) — always true — and the TRUE arm assigns the tainted `param`, so the reachable arm carries taint and only the `: \"...\"` const arm is dead. The Java ternary diamond split + fold must prune the DEAD const arm while keeping the live `bar = param`, so the command-injection finding at `r.exec(cmd + bar)` MUST still fire. Zero-false-negative guard: proves the diamond/fold never prunes the reachable tainted arm.",
|
||||
"tags": [
|
||||
"taint",
|
||||
"cmdi",
|
||||
"servlet",
|
||||
"runtime",
|
||||
"ternary",
|
||||
"const-fold",
|
||||
"no-false-negative"
|
||||
],
|
||||
"modes": [
|
||||
"full"
|
||||
],
|
||||
"strict_unexpected": [
|
||||
"taint-unsanitised-flow"
|
||||
],
|
||||
"expected": [
|
||||
{
|
||||
"rule_id": "taint-unsanitised-flow",
|
||||
"severity": "HIGH",
|
||||
"must_match": true,
|
||||
"line_range": [
|
||||
19,
|
||||
19
|
||||
],
|
||||
"evidence_contains": [],
|
||||
"notes": "request.getHeader (line 12) flows into bar on the always-taken true arm (line 15), then into r.exec at line 19. Exactly one finding survives.",
|
||||
"max_count": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
21
tests/fixtures/real_world/java/taint/cmdi_ternary_param_vuln.java
vendored
Normal file
21
tests/fixtures/real_world/java/taint/cmdi_ternary_param_vuln.java
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import java.io.*;
|
||||
import javax.servlet.http.*;
|
||||
|
||||
// Constant-condition ternary, VULNERABLE polarity. `(500/42) + num` is
|
||||
// `11 + 196 = 207 > 200` (integer division) — ALWAYS true — and the TRUE arm
|
||||
// selects the tainted `param`, so the reachable arm carries taint and only the
|
||||
// `: "..."` const arm is dead. The fold must prune the dead const arm while
|
||||
// keeping the live `param`, so the cmdi finding at `r.exec` MUST still fire.
|
||||
public class TernaryParamVuln extends HttpServlet {
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
String param = request.getHeader("vector");
|
||||
|
||||
int num = 196;
|
||||
String bar = (500 / 42) + num > 200 ? param : "This_should_never_happen";
|
||||
|
||||
String cmd = "echo ";
|
||||
Runtime r = Runtime.getRuntime();
|
||||
Process p = r.exec(cmd + bar);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue