up
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Findings Ledger CI / build-test (push) Has been cancelled
Findings Ledger CI / migration-validation (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
cryptopro-linux-csp / build-and-test (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
sm-remote-ci / build-and-test (push) Has been cancelled
Findings Ledger CI / generate-manifest (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Findings Ledger CI / build-test (push) Has been cancelled
Findings Ledger CI / migration-validation (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
cryptopro-linux-csp / build-and-test (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
sm-remote-ci / build-and-test (push) Has been cancelled
Findings Ledger CI / generate-manifest (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
id: "java-micronaut-deserialize:203"
|
||||
language: java
|
||||
project: micronaut-deserialize
|
||||
version: "1.0.0"
|
||||
description: "Micronaut-style controller performs unsafe deserialization on request payload"
|
||||
entrypoints:
|
||||
- "POST /mn/upload"
|
||||
sinks:
|
||||
- id: "MicronautDeserialize::handleUpload"
|
||||
path: "bench.reachability.micronaut.Controller.handleUpload"
|
||||
kind: "custom"
|
||||
location:
|
||||
file: src/Controller.java
|
||||
line: 10
|
||||
notes: "ObjectInputStream on user-controlled payload"
|
||||
environment:
|
||||
os_image: "eclipse-temurin:21-jdk"
|
||||
runtime:
|
||||
java: "21"
|
||||
source_date_epoch: 1730000000
|
||||
resource_limits:
|
||||
cpu: "2"
|
||||
memory: "4Gi"
|
||||
build:
|
||||
command: "./build/build.sh"
|
||||
source_date_epoch: 1730000000
|
||||
outputs:
|
||||
artifact_path: outputs/binary.tar.gz
|
||||
sbom_path: outputs/sbom.cdx.json
|
||||
coverage_path: outputs/coverage.json
|
||||
traces_dir: outputs/traces
|
||||
attestation_path: outputs/attestation.json
|
||||
test:
|
||||
command: "./build/build.sh"
|
||||
expected_coverage: []
|
||||
expected_traces: []
|
||||
env:
|
||||
JAVA_TOOL_OPTIONS: "-ea"
|
||||
ground_truth:
|
||||
summary: "Deserialization reachable"
|
||||
evidence_files:
|
||||
- "../benchmark/truth/java-micronaut-deserialize.json"
|
||||
sandbox:
|
||||
network: loopback
|
||||
privileges: rootless
|
||||
redaction:
|
||||
pii: false
|
||||
policy: "benchmark-default/v1"
|
||||
@@ -0,0 +1,8 @@
|
||||
case_id: "java-micronaut-deserialize:203"
|
||||
entries:
|
||||
http:
|
||||
- id: "POST /mn/upload"
|
||||
route: "/mn/upload"
|
||||
method: "POST"
|
||||
handler: "Controller.handleUpload"
|
||||
description: "Binary payload base64-deserialized"
|
||||
@@ -0,0 +1,12 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.stellaops.bench</groupId>
|
||||
<artifactId>micronaut-deserialize</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
</project>
|
||||
@@ -0,0 +1,24 @@
|
||||
package bench.reachability.micronaut;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Base64;
|
||||
import java.io.*;
|
||||
|
||||
public class Controller {
|
||||
// Unsafe deserialization sink (reachable)
|
||||
public static Response handleUpload(Map<String, String> body) {
|
||||
String payload = body.get("payload");
|
||||
if (payload == null) {
|
||||
return new Response(400, "bad request");
|
||||
}
|
||||
try (ObjectInputStream ois = new ObjectInputStream(
|
||||
new ByteArrayInputStream(Base64.getDecoder().decode(payload)))) {
|
||||
Object obj = ois.readObject();
|
||||
return new Response(200, obj.toString());
|
||||
} catch (Exception ex) {
|
||||
return new Response(500, ex.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
public record Response(int status, String body) {}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package bench.reachability.micronaut;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.Base64;
|
||||
|
||||
// Simple assertion-based oracle (JUnit-free for offline determinism)
|
||||
public class ControllerTest {
|
||||
private static String serialize(Object obj) throws IOException {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {
|
||||
oos.writeObject(obj);
|
||||
}
|
||||
return Base64.getEncoder().encodeToString(bos.toByteArray());
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Map<String, String> body = Map.of("payload", serialize("micronaut"));
|
||||
var res = Controller.handleUpload(body);
|
||||
assert res.status() == 200 : "status";
|
||||
assert res.body().equals("micronaut") : "body";
|
||||
|
||||
File outDir = new File("outputs");
|
||||
outDir.mkdirs();
|
||||
try (FileWriter fw = new FileWriter(new File(outDir, "SINK_REACHED"))) {
|
||||
fw.write("true");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
id: "java-micronaut-guarded:204"
|
||||
language: java
|
||||
project: micronaut-guarded
|
||||
version: "1.0.0"
|
||||
description: "Micronaut-style controller guards deserialization behind ALLOW_MN_DESER flag (unreachable by default)"
|
||||
entrypoints:
|
||||
- "POST /mn/upload"
|
||||
sinks:
|
||||
- id: "MicronautDeserializeGuarded::handleUpload"
|
||||
path: "bench.reachability.micronautguard.Controller.handleUpload"
|
||||
kind: "custom"
|
||||
location:
|
||||
file: src/Controller.java
|
||||
line: 11
|
||||
notes: "ObjectInputStream gated by ALLOW_MN_DESER"
|
||||
environment:
|
||||
os_image: "eclipse-temurin:21-jdk"
|
||||
runtime:
|
||||
java: "21"
|
||||
source_date_epoch: 1730000000
|
||||
resource_limits:
|
||||
cpu: "2"
|
||||
memory: "4Gi"
|
||||
build:
|
||||
command: "./build/build.sh"
|
||||
source_date_epoch: 1730000000
|
||||
outputs:
|
||||
artifact_path: outputs/binary.tar.gz
|
||||
sbom_path: outputs/sbom.cdx.json
|
||||
coverage_path: outputs/coverage.json
|
||||
traces_dir: outputs/traces
|
||||
attestation_path: outputs/attestation.json
|
||||
test:
|
||||
command: "./build/build.sh"
|
||||
expected_coverage: []
|
||||
expected_traces: []
|
||||
env:
|
||||
JAVA_TOOL_OPTIONS: "-ea"
|
||||
ground_truth:
|
||||
summary: "Guard blocks deserialization unless ALLOW_MN_DESER=true"
|
||||
evidence_files:
|
||||
- "../benchmark/truth/java-micronaut-guarded.json"
|
||||
sandbox:
|
||||
network: loopback
|
||||
privileges: rootless
|
||||
redaction:
|
||||
pii: false
|
||||
policy: "benchmark-default/v1"
|
||||
@@ -0,0 +1,8 @@
|
||||
case_id: "java-micronaut-guarded:204"
|
||||
entries:
|
||||
http:
|
||||
- id: "POST /mn/upload"
|
||||
route: "/mn/upload"
|
||||
method: "POST"
|
||||
handler: "Controller.handleUpload"
|
||||
description: "Deserialization guarded by ALLOW_MN_DESER flag"
|
||||
@@ -0,0 +1,12 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.stellaops.bench</groupId>
|
||||
<artifactId>micronaut-guarded</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
</project>
|
||||
@@ -0,0 +1,27 @@
|
||||
package bench.reachability.micronautguard;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Base64;
|
||||
import java.io.*;
|
||||
|
||||
public class Controller {
|
||||
// Deserialization behind feature flag; unreachable unless ALLOW_MN_DESER=true
|
||||
public static Response handleUpload(Map<String, String> body, Map<String, String> env) {
|
||||
if (!"true".equals(env.getOrDefault("ALLOW_MN_DESER", "false"))) {
|
||||
return new Response(403, "forbidden");
|
||||
}
|
||||
String payload = body.get("payload");
|
||||
if (payload == null) {
|
||||
return new Response(400, "bad request");
|
||||
}
|
||||
try (ObjectInputStream ois = new ObjectInputStream(
|
||||
new ByteArrayInputStream(Base64.getDecoder().decode(payload)))) {
|
||||
Object obj = ois.readObject();
|
||||
return new Response(200, obj.toString());
|
||||
} catch (Exception ex) {
|
||||
return new Response(500, ex.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
public record Response(int status, String body) {}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package bench.reachability.micronautguard;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.Base64;
|
||||
|
||||
public class ControllerTest {
|
||||
private static String serialize(Object obj) throws IOException {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {
|
||||
oos.writeObject(obj);
|
||||
}
|
||||
return Base64.getEncoder().encodeToString(bos.toByteArray());
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Map<String, String> body = Map.of("payload", serialize("blocked"));
|
||||
Map<String, String> env = Map.of("ALLOW_MN_DESER", "false");
|
||||
var res = Controller.handleUpload(body, env);
|
||||
assert res.status() == 403 : "status";
|
||||
assert res.body().equals("forbidden") : "body";
|
||||
|
||||
File outDir = new File("outputs");
|
||||
outDir.mkdirs();
|
||||
try (FileWriter fw = new FileWriter(new File(outDir, "SINK_BLOCKED"))) {
|
||||
fw.write("true");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
id: "java-spring-reflection:205"
|
||||
language: java
|
||||
project: spring-reflection
|
||||
version: "1.0.0"
|
||||
description: "Spring-style controller exposes reflection endpoint that loads arbitrary classes"
|
||||
entrypoints:
|
||||
- "POST /api/reflect"
|
||||
sinks:
|
||||
- id: "SpringReflection::run"
|
||||
path: "bench.reachability.springreflection.ReflectController.run"
|
||||
kind: "custom"
|
||||
location:
|
||||
file: src/ReflectController.java
|
||||
line: 7
|
||||
notes: "User-controlled Class.forName + newInstance"
|
||||
environment:
|
||||
os_image: "eclipse-temurin:21-jdk"
|
||||
runtime:
|
||||
java: "21"
|
||||
source_date_epoch: 1730000000
|
||||
resource_limits:
|
||||
cpu: "2"
|
||||
memory: "4Gi"
|
||||
build:
|
||||
command: "./build/build.sh"
|
||||
source_date_epoch: 1730000000
|
||||
outputs:
|
||||
artifact_path: outputs/binary.tar.gz
|
||||
sbom_path: outputs/sbom.cdx.json
|
||||
coverage_path: outputs/coverage.json
|
||||
traces_dir: outputs/traces
|
||||
attestation_path: outputs/attestation.json
|
||||
test:
|
||||
command: "./build/build.sh"
|
||||
expected_coverage: []
|
||||
expected_traces: []
|
||||
env:
|
||||
JAVA_TOOL_OPTIONS: "-ea"
|
||||
ground_truth:
|
||||
summary: "Reflection sink reachable with user-controlled class name"
|
||||
evidence_files:
|
||||
- "../benchmark/truth/java-spring-reflection.json"
|
||||
sandbox:
|
||||
network: loopback
|
||||
privileges: rootless
|
||||
redaction:
|
||||
pii: false
|
||||
policy: "benchmark-default/v1"
|
||||
@@ -0,0 +1,8 @@
|
||||
case_id: "java-spring-reflection:205"
|
||||
entries:
|
||||
http:
|
||||
- id: "POST /api/reflect"
|
||||
route: "/api/reflect"
|
||||
method: "POST"
|
||||
handler: "ReflectController.run"
|
||||
description: "Reflection endpoint loads arbitrary classes"
|
||||
@@ -0,0 +1,12 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.stellaops.bench</groupId>
|
||||
<artifactId>spring-reflection</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
</project>
|
||||
@@ -0,0 +1,29 @@
|
||||
package bench.reachability.springreflection;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ReflectController {
|
||||
// Reflection sink: user controls Class.forName target
|
||||
public static Response run(Map<String, String> body) {
|
||||
String className = body.get("class");
|
||||
if (className == null || className.isBlank()) {
|
||||
return new Response(400, "bad request");
|
||||
}
|
||||
try {
|
||||
Class<?> type = Class.forName(className);
|
||||
Object instance = type.getDeclaredConstructor().newInstance();
|
||||
return new Response(200, instance.toString());
|
||||
} catch (Exception ex) {
|
||||
return new Response(500, ex.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
public record Response(int status, String body) {}
|
||||
|
||||
public static class Marker {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "marker";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package bench.reachability.springreflection;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.util.Map;
|
||||
|
||||
public class ReflectControllerTest {
|
||||
public static void main(String[] args) throws Exception {
|
||||
Map<String, String> body = Map.of("class", ReflectController.Marker.class.getName());
|
||||
var res = ReflectController.run(body);
|
||||
assert res.status() == 200 : "status";
|
||||
assert res.body().equals("marker") : "body";
|
||||
|
||||
File outDir = new File("outputs");
|
||||
outDir.mkdirs();
|
||||
try (FileWriter fw = new FileWriter(new File(outDir, "SINK_REACHED"))) {
|
||||
fw.write("true");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user