mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-15 20:05:13 +02:00
refactor(dynamic): add multi-method support to RouteShape, update framework bindings, and improve test coverage
This commit is contained in:
parent
4bcdec3a1b
commit
ca075a7141
55 changed files with 524 additions and 215 deletions
|
|
@ -1,8 +1,11 @@
|
|||
// Phase 20 (Track M.2) — Kafka Java benign control.
|
||||
// `org.springframework.kafka` adapter marker preserved.
|
||||
|
||||
import org.springframework.kafka.annotation.KafkaListener;
|
||||
|
||||
public class Benign {
|
||||
public Benign() {}
|
||||
|
||||
@KafkaListener(topics = "orders")
|
||||
public void onMessage(String body) throws Exception {
|
||||
new ProcessBuilder("echo", body).inheritIO().start().waitFor();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
// Phase 20 (Track M.2) — Kafka Java vuln fixture.
|
||||
//
|
||||
// Marker line so the kafka-java framework adapter binds:
|
||||
// `org.springframework.kafka` consumer entry point. Annotation is
|
||||
// elided so javac compiles without the Spring jar; the dynamic harness
|
||||
// invokes onMessage reflectively.
|
||||
|
||||
import org.springframework.kafka.annotation.KafkaListener;
|
||||
|
||||
public class Vuln {
|
||||
public Vuln() {}
|
||||
|
||||
@KafkaListener(topics = "orders")
|
||||
public void onMessage(String body) throws Exception {
|
||||
// SINK: tainted body concatenated into shell command
|
||||
new ProcessBuilder("sh", "-c", "echo " + body).inheritIO().start().waitFor();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
// Phase 20 (Track M.2) — RabbitMQ Java benign control.
|
||||
// `org.springframework.amqp.rabbit` adapter marker preserved.
|
||||
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
|
||||
public class Benign {
|
||||
public Benign() {}
|
||||
|
||||
@RabbitListener(queues = "work")
|
||||
public void onMessage(String messageId, String body) throws Exception {
|
||||
new ProcessBuilder("echo", body).inheritIO().start().waitFor();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
// Phase 20 (Track M.2) — RabbitMQ Java vuln fixture.
|
||||
// `org.springframework.amqp.rabbit` consumer marker preserved;
|
||||
// annotation elided so javac compiles without the Spring AMQP jar.
|
||||
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
|
||||
public class Vuln {
|
||||
public Vuln() {}
|
||||
|
||||
@RabbitListener(queues = "work")
|
||||
public void onMessage(String messageId, String body) throws Exception {
|
||||
// SINK: tainted body concatenated into shell command
|
||||
new ProcessBuilder("sh", "-c", "echo " + body).inheritIO().start().waitFor();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
// Phase 20 (Track M.2) — SQS Java benign control.
|
||||
// `io.awspring.cloud.sqs` adapter marker preserved.
|
||||
|
||||
import io.awspring.cloud.sqs.annotation.SqsListener;
|
||||
|
||||
public class Benign {
|
||||
public Benign() {}
|
||||
|
||||
@SqsListener("jobs")
|
||||
public void handleMessage(java.util.Map<String, String> env) throws Exception {
|
||||
String body = env != null ? env.getOrDefault("Body", "") : "";
|
||||
new ProcessBuilder("echo", body).inheritIO().start().waitFor();
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
// Phase 20 (Track M.2) — SQS Java vuln fixture.
|
||||
// `io.awspring.cloud.sqs` consumer entry point — annotation elided so
|
||||
// javac compiles without the Spring Cloud AWS jar.
|
||||
|
||||
import io.awspring.cloud.sqs.annotation.SqsListener;
|
||||
|
||||
public class Vuln {
|
||||
public Vuln() {}
|
||||
|
||||
@SqsListener("jobs")
|
||||
public void handleMessage(java.util.Map<String, String> env) throws Exception {
|
||||
String body = env != null ? env.getOrDefault("Body", "") : "";
|
||||
// SINK: tainted Body concatenated into shell command
|
||||
|
|
|
|||
|
|
@ -183,7 +183,9 @@ mod e2e_json_parse_depth {
|
|||
Lang::Go => "go",
|
||||
Lang::Rust => "rust",
|
||||
Lang::Java => "java",
|
||||
_ => unreachable!("JSON_PARSE depth e2e covers JS / Python / Ruby / PHP / Go / Rust / Java only"),
|
||||
_ => unreachable!(
|
||||
"JSON_PARSE depth e2e covers JS / Python / Ruby / PHP / Go / Rust / Java only"
|
||||
),
|
||||
})
|
||||
.join(fixture);
|
||||
let tmp = TempDir::new().expect("create tempdir");
|
||||
|
|
@ -230,7 +232,9 @@ mod e2e_json_parse_depth {
|
|||
Lang::Go => "go",
|
||||
Lang::Rust => "cargo",
|
||||
Lang::Java => "javac",
|
||||
_ => unreachable!("JSON_PARSE depth e2e covers JS / Python / Ruby / PHP / Go / Rust / Java only"),
|
||||
_ => unreachable!(
|
||||
"JSON_PARSE depth e2e covers JS / Python / Ruby / PHP / Go / Rust / Java only"
|
||||
),
|
||||
};
|
||||
if !command_available(required) {
|
||||
eprintln!("SKIP {lang:?} {fixture}: missing toolchain {required}");
|
||||
|
|
|
|||
|
|
@ -326,8 +326,9 @@ mod e2e_phase_20 {
|
|||
use tempfile::TempDir;
|
||||
|
||||
fn command_available(bin: &str) -> bool {
|
||||
let version_arg = if bin == "go" { "version" } else { "--version" };
|
||||
Command::new(bin)
|
||||
.arg("--version")
|
||||
.arg(version_arg)
|
||||
.output()
|
||||
.map(|o| o.status.success())
|
||||
.unwrap_or(false)
|
||||
|
|
@ -484,7 +485,10 @@ mod e2e_phase_20 {
|
|||
let Some(outcome) = run(Lang::Python, "sqs_python", "vuln.py", "handler", "jobs") else {
|
||||
return;
|
||||
};
|
||||
assert!(outcome.triggered_by.is_some());
|
||||
assert!(
|
||||
outcome.triggered_by.is_some(),
|
||||
"sqs-python MessageHandler vuln must Confirm via run_spec; got {outcome:?}",
|
||||
);
|
||||
let diff = outcome.differential.as_ref().expect("Confirmed");
|
||||
assert_eq!(diff.verdict, DifferentialVerdict::Confirmed);
|
||||
}
|
||||
|
|
@ -500,7 +504,10 @@ mod e2e_phase_20 {
|
|||
) else {
|
||||
return;
|
||||
};
|
||||
assert!(outcome.triggered_by.is_some());
|
||||
assert!(
|
||||
outcome.triggered_by.is_some(),
|
||||
"pubsub-python MessageHandler vuln must Confirm via run_spec; got {outcome:?}",
|
||||
);
|
||||
let diff = outcome.differential.as_ref().expect("Confirmed");
|
||||
assert_eq!(diff.verdict, DifferentialVerdict::Confirmed);
|
||||
}
|
||||
|
|
@ -516,7 +523,10 @@ mod e2e_phase_20 {
|
|||
) else {
|
||||
return;
|
||||
};
|
||||
assert!(outcome.triggered_by.is_some());
|
||||
assert!(
|
||||
outcome.triggered_by.is_some(),
|
||||
"rabbit-python MessageHandler vuln must Confirm via run_spec; got {outcome:?}",
|
||||
);
|
||||
let diff = outcome.differential.as_ref().expect("Confirmed");
|
||||
assert_eq!(diff.verdict, DifferentialVerdict::Confirmed);
|
||||
}
|
||||
|
|
@ -534,4 +544,71 @@ mod e2e_phase_20 {
|
|||
let diff = outcome.differential.as_ref().expect("Confirmed");
|
||||
assert_eq!(diff.verdict, DifferentialVerdict::Confirmed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn kafka_java_vuln_confirms_via_run_spec() {
|
||||
let Some(outcome) = run(Lang::Java, "kafka_java", "Vuln.java", "onMessage", "orders")
|
||||
else {
|
||||
return;
|
||||
};
|
||||
assert!(
|
||||
outcome.triggered_by.is_some(),
|
||||
"kafka-java MessageHandler vuln must Confirm via run_spec; got {outcome:?}",
|
||||
);
|
||||
let diff = outcome.differential.as_ref().expect("Confirmed");
|
||||
assert_eq!(diff.verdict, DifferentialVerdict::Confirmed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sqs_java_vuln_confirms_via_run_spec() {
|
||||
let Some(outcome) = run(Lang::Java, "sqs_java", "Vuln.java", "handleMessage", "jobs")
|
||||
else {
|
||||
return;
|
||||
};
|
||||
assert!(
|
||||
outcome.triggered_by.is_some(),
|
||||
"sqs-java MessageHandler vuln must Confirm via run_spec; got {outcome:?}",
|
||||
);
|
||||
let diff = outcome.differential.as_ref().expect("Confirmed");
|
||||
assert_eq!(diff.verdict, DifferentialVerdict::Confirmed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rabbit_java_vuln_confirms_via_run_spec() {
|
||||
let Some(outcome) = run(Lang::Java, "rabbit_java", "Vuln.java", "onMessage", "work") else {
|
||||
return;
|
||||
};
|
||||
assert!(
|
||||
outcome.triggered_by.is_some(),
|
||||
"rabbit-java MessageHandler vuln must Confirm via run_spec; got {outcome:?}",
|
||||
);
|
||||
let diff = outcome.differential.as_ref().expect("Confirmed");
|
||||
assert_eq!(diff.verdict, DifferentialVerdict::Confirmed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pubsub_go_vuln_confirms_via_run_spec() {
|
||||
let Some(outcome) = run(Lang::Go, "pubsub_go", "vuln.go", "OnMessage", "my-sub") else {
|
||||
return;
|
||||
};
|
||||
assert!(
|
||||
outcome.triggered_by.is_some(),
|
||||
"pubsub-go MessageHandler vuln must Confirm via run_spec; got {outcome:?}",
|
||||
);
|
||||
let diff = outcome.differential.as_ref().expect("Confirmed");
|
||||
assert_eq!(diff.verdict, DifferentialVerdict::Confirmed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nats_go_vuln_confirms_via_run_spec() {
|
||||
let Some(outcome) = run(Lang::Go, "nats_go", "vuln.go", "OnMessage", "events") else {
|
||||
return;
|
||||
};
|
||||
assert!(
|
||||
outcome.triggered_by.is_some(),
|
||||
"nats-go MessageHandler vuln must Confirm via run_spec; got {outcome:?}",
|
||||
);
|
||||
let diff = outcome.differential.as_ref().expect("Confirmed");
|
||||
assert_eq!(diff.verdict, DifferentialVerdict::Confirmed);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue