From 1d9f42484a283937c1a7e13c37cb8e3da34f8b91 Mon Sep 17 00:00:00 2001 From: "alejandro.gonzalez" Date: Thu, 14 May 2026 11:19:25 +0200 Subject: [PATCH 1/2] feat(appsec/java): add SCA reachability system tests for Java - Add ScaReachability.java controller to spring-boot weblog with /sca/vulnerable-call and /sca/vulnerable-call-alt endpoints (call snakeyaml Yaml.load(), vulnerable via GHSA-mjmj-j48q-9wg2) - Add Java entry to _LANG_CONFIG in test_sca_reachability.py (org.yaml:snakeyaml, callsite: ScaReachability.scaVulnerableCall) - Enable SCA reachability tests for spring-boot in manifests/java.yml (v1.63.0-SNAPSHOT, all other weblogs irrelevant) Relates to DataDog/dd-trace-java#11352 --- manifests/java.yml | 30 +++++++++++++++---- tests/appsec/test_sca_reachability.py | 6 ++++ .../springboot/ScaReachability.java | 25 ++++++++++++++++ 3 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 utils/build/docker/java/spring-boot/src/main/java/com/datadoghq/system_tests/springboot/ScaReachability.java diff --git a/manifests/java.yml b/manifests/java.yml index 6ea0f0424d8..481fe1d1f9b 100644 --- a/manifests/java.yml +++ b/manifests/java.yml @@ -2432,11 +2432,31 @@ manifest: akka-http: v1.22.0 play: v1.22.0 spring-boot-3-native: irrelevant (GraalVM. Tracing support only) - tests/appsec/test_sca_reachability.py::Test_SCA_Reachability_CVE_After_Vulnerable_Call: missing_feature - tests/appsec/test_sca_reachability.py::Test_SCA_Reachability_CVE_Registered_At_Load_Time: missing_feature - tests/appsec/test_sca_reachability.py::Test_SCA_Reachability_Deduplication: missing_feature - tests/appsec/test_sca_reachability.py::Test_SCA_Reachability_Dependencies_Have_Metadata: missing_feature - tests/appsec/test_sca_reachability.py::Test_SCA_Reachability_First_Hit_Wins: missing_feature + tests/appsec/test_sca_reachability.py::Test_SCA_Reachability_CVE_After_Vulnerable_Call: + - weblog_declaration: + "*": irrelevant (endpoint only implemented in spring-boot weblog) + spring-boot: v1.63.0-SNAPSHOT + spring-boot-3-native: irrelevant (GraalVM. Tracing support only) + tests/appsec/test_sca_reachability.py::Test_SCA_Reachability_CVE_Registered_At_Load_Time: + - weblog_declaration: + "*": irrelevant (endpoint only implemented in spring-boot weblog) + spring-boot: v1.63.0-SNAPSHOT + spring-boot-3-native: irrelevant (GraalVM. Tracing support only) + tests/appsec/test_sca_reachability.py::Test_SCA_Reachability_Deduplication: + - weblog_declaration: + "*": irrelevant (endpoint only implemented in spring-boot weblog) + spring-boot: v1.63.0-SNAPSHOT + spring-boot-3-native: irrelevant (GraalVM. Tracing support only) + tests/appsec/test_sca_reachability.py::Test_SCA_Reachability_Dependencies_Have_Metadata: + - weblog_declaration: + "*": irrelevant (endpoint only implemented in spring-boot weblog) + spring-boot: v1.63.0-SNAPSHOT + spring-boot-3-native: irrelevant (GraalVM. Tracing support only) + tests/appsec/test_sca_reachability.py::Test_SCA_Reachability_First_Hit_Wins: + - weblog_declaration: + "*": irrelevant (endpoint only implemented in spring-boot weblog) + spring-boot: v1.63.0-SNAPSHOT + spring-boot-3-native: irrelevant (GraalVM. Tracing support only) tests/appsec/test_service_activation_metric.py::TestServiceActivationEnvVarConfigurationMetric: missing_feature tests/appsec/test_service_activation_metric.py::TestServiceActivationEnvVarMetric: missing_feature tests/appsec/test_service_activation_metric.py::TestServiceActivationRemoteConfigMetric: missing_feature diff --git a/tests/appsec/test_sca_reachability.py b/tests/appsec/test_sca_reachability.py index 6de0afc3608..4052ca5c9a9 100644 --- a/tests/appsec/test_sca_reachability.py +++ b/tests/appsec/test_sca_reachability.py @@ -25,6 +25,12 @@ "path": "app.py", "symbol": "sca_requests_vulnerable_call", }, + "java": { + "cve_id": "GHSA-mjmj-j48q-9wg2", + "vulnerable_dep": "org.yaml:snakeyaml", + "path": "com.datadoghq.system_tests.springboot.ScaReachability", + "symbol": "scaVulnerableCall", + }, } diff --git a/utils/build/docker/java/spring-boot/src/main/java/com/datadoghq/system_tests/springboot/ScaReachability.java b/utils/build/docker/java/spring-boot/src/main/java/com/datadoghq/system_tests/springboot/ScaReachability.java new file mode 100644 index 00000000000..e9121e95f60 --- /dev/null +++ b/utils/build/docker/java/spring-boot/src/main/java/com/datadoghq/system_tests/springboot/ScaReachability.java @@ -0,0 +1,25 @@ +package com.datadoghq.system_tests.springboot; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.yaml.snakeyaml.Yaml; + +@RestController +@RequestMapping("/sca") +public class ScaReachability { + + @GetMapping("/vulnerable-call") + public String scaVulnerableCall() { + Yaml yaml = new Yaml(); + yaml.load("key: value"); + return "OK"; + } + + @GetMapping("/vulnerable-call-alt") + public String scaVulnerableCallAlt() { + Yaml yaml = new Yaml(); + yaml.load("alt: value"); + return "OK"; + } +} From ead7339165efe4200d7dcea2d4552720e8eb84d8 Mon Sep 17 00:00:00 2001 From: "alejandro.gonzalez" Date: Thu, 14 May 2026 12:27:11 +0200 Subject: [PATCH 2/2] fix(appsec/java): preload Yaml class at startup via @PostConstruct Force org.yaml.snakeyaml.Yaml to load during Spring context initialization, before any HTTP request. This ensures the SCA transformer registers the CVE with reached=[] on startup, and a telemetry heartbeat can send that state before test setups call /sca/vulnerable-call. Without this, the class loads lazily on the first endpoint request, making registerCve() and recordHit() fire in the same request with no heartbeat window between them. --- .../system_tests/springboot/ScaReachability.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/utils/build/docker/java/spring-boot/src/main/java/com/datadoghq/system_tests/springboot/ScaReachability.java b/utils/build/docker/java/spring-boot/src/main/java/com/datadoghq/system_tests/springboot/ScaReachability.java index e9121e95f60..8be99c94ea3 100644 --- a/utils/build/docker/java/spring-boot/src/main/java/com/datadoghq/system_tests/springboot/ScaReachability.java +++ b/utils/build/docker/java/spring-boot/src/main/java/com/datadoghq/system_tests/springboot/ScaReachability.java @@ -1,5 +1,6 @@ package com.datadoghq.system_tests.springboot; +import javax.annotation.PostConstruct; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -9,6 +10,15 @@ @RequestMapping("/sca") public class ScaReachability { + @PostConstruct + private void preloadVulnerableClass() { + // Force Yaml class load during Spring startup so the SCA transformer can register the CVE + // with reached=[] before any HTTP request triggers yaml.load(). Without this, the class + // loads lazily on the first /sca/vulnerable-call request, causing registerCve() and + // recordHit() to fire in the same request with no heartbeat window between them. + new Yaml(); + } + @GetMapping("/vulnerable-call") public String scaVulnerableCall() { Yaml yaml = new Yaml();