From c48e267cc0b79d43ed64137ae69455a7706848dd Mon Sep 17 00:00:00 2001 From: Enrico Molino Date: Mon, 4 May 2026 18:09:18 +0200 Subject: [PATCH 1/8] jjwt dependency update --- symphony-bdk-bom/build.gradle | 4 ++- symphony-bdk-core/build.gradle | 4 ++- .../symphony/bdk/core/auth/jwt/JwtHelper.java | 27 ++++++++++--------- .../symphony-bdk-http-jersey2/build.gradle | 5 ++-- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/symphony-bdk-bom/build.gradle b/symphony-bdk-bom/build.gradle index c64222a30..c9eef1876 100644 --- a/symphony-bdk-bom/build.gradle +++ b/symphony-bdk-bom/build.gradle @@ -55,7 +55,9 @@ dependencies { api 'org.apache.commons:commons-text:1.14.0' api 'commons-logging:commons-logging:1.3.5' api 'com.brsanthu:migbase64:2.2' - api 'io.jsonwebtoken:jjwt:0.9.1' + api 'io.jsonwebtoken:jjwt-api:0.13.0' + api 'io.jsonwebtoken:jjwt-impl:0.13.0' + api 'io.jsonwebtoken:jjwt-jackson:0.13.0' api 'org.bouncycastle:bcpkix-jdk18on:1.79' api 'com.google.code.findbugs:jsr305:3.0.2' diff --git a/symphony-bdk-core/build.gradle b/symphony-bdk-core/build.gradle index 4a3792ce8..19edaae5d 100644 --- a/symphony-bdk-core/build.gradle +++ b/symphony-bdk-core/build.gradle @@ -47,7 +47,9 @@ dependencies { implementation 'org.apache.commons:commons-lang3' implementation 'org.apache.commons:commons-text' implementation 'com.brsanthu:migbase64' - implementation 'io.jsonwebtoken:jjwt' + implementation 'io.jsonwebtoken:jjwt-api' + runtimeOnly 'io.jsonwebtoken:jjwt-impl' + runtimeOnly 'io.jsonwebtoken:jjwt-jackson' implementation 'org.bouncycastle:bcpkix-jdk18on' api 'com.fasterxml.jackson.core:jackson-databind' implementation 'io.github.resilience4j:resilience4j-retry' diff --git a/symphony-bdk-core/src/main/java/com/symphony/bdk/core/auth/jwt/JwtHelper.java b/symphony-bdk-core/src/main/java/com/symphony/bdk/core/auth/jwt/JwtHelper.java index 2f8f7b9e1..0c376c27d 100644 --- a/symphony-bdk-core/src/main/java/com/symphony/bdk/core/auth/jwt/JwtHelper.java +++ b/symphony-bdk-core/src/main/java/com/symphony/bdk/core/auth/jwt/JwtHelper.java @@ -9,7 +9,6 @@ import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtException; import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; import org.apiguardian.api.API; import org.bouncycastle.asn1.pkcs.RSAPrivateKey; import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; @@ -23,7 +22,6 @@ import java.io.StringReader; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; -import java.security.Key; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; @@ -65,7 +63,7 @@ public class JwtHelper { /** - * Creates a JWT with the provided user name and expiration date, signed with the provided private key. + * Creates a JWT with the provided username and expiration date, signed with the provided private key. * * @param user the username to authenticate; will be verified by the pod * @param expiration of the authentication request in milliseconds; cannot be longer than the value defined on the @@ -75,16 +73,16 @@ public class JwtHelper { * the public key stored for the user * @return a signed JWT for a specific user (or subject) */ - public static String createSignedJwt(String user, long expiration, Key privateKey) { + public static String createSignedJwt(String user, long expiration, PrivateKey privateKey) { return Jwts.builder() - .setSubject(user) - .setExpiration(new Date(System.currentTimeMillis() + expiration)) - .signWith(SignatureAlgorithm.RS512, privateKey) + .subject(user) + .expiration(new Date(System.currentTimeMillis() + expiration)) + .signWith(privateKey, Jwts.SIG.RS512) .compact(); } /** - * Creates a RSA Private Key from a PEM String. It supports PKCS#1 and PKCS#8 string formats. + * Creates an RSA Private Key from a PEM String. It supports PKCS#1 and PKCS#8 string formats. * * @param pemPrivateKey RSA Private Key content * @return a {@link PrivateKey} instance @@ -110,18 +108,21 @@ else if (pemPrivateKey.contains(PEM_RSA_PRIVATE_START)) { /** * Validates a jwt against a certificate. * - * @param jwt + * @param jwt string of the jwt to be validated * @param certificate string of the X.509 certificate content in pem format. - * @return the content of jwt clain "user" if jwt is successfully validated. + * @return the content of jwt claim "user" if jwt is successfully validated. * @throws AuthInitializationException if certificate or jwt are invalid. */ public static UserClaim validateJwt(String jwt, String certificate) throws AuthInitializationException { final Certificate x509Certificate = parseX509Certificate(certificate); try { - final Claims body = Jwts.parser().setSigningKey(x509Certificate.getPublicKey()) - .parseClaimsJws(jwt).getBody(); - return mapper.convertValue(body.get("user"), UserClaim.class); + final Claims claims = Jwts.parser() + .verifyWith(x509Certificate.getPublicKey()) + .build() + .parseSignedClaims(jwt) + .getPayload(); + return mapper.convertValue(claims.get("user"), UserClaim.class); } catch (JwtException e) { throw new AuthInitializationException("Unable to validate JWT", e); } diff --git a/symphony-bdk-http/symphony-bdk-http-jersey2/build.gradle b/symphony-bdk-http/symphony-bdk-http-jersey2/build.gradle index 2ea028923..130379808 100644 --- a/symphony-bdk-http/symphony-bdk-http-jersey2/build.gradle +++ b/symphony-bdk-http/symphony-bdk-http-jersey2/build.gradle @@ -16,7 +16,9 @@ dependencies { implementation 'org.slf4j:slf4j-api' implementation 'org.apiguardian:apiguardian-api' - implementation 'io.jsonwebtoken:jjwt' + implementation 'io.jsonwebtoken:jjwt-api' + runtimeOnly 'io.jsonwebtoken:jjwt-impl' + runtimeOnly 'io.jsonwebtoken:jjwt-jackson' implementation 'org.bouncycastle:bcpkix-jdk18on' implementation 'commons-io:commons-io' implementation 'org.apache.commons:commons-lang3' @@ -42,4 +44,3 @@ dependencies { testImplementation 'org.mockito:mockito-junit-jupiter' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } - From 63feddad6125c40edf48e5bdbd0aac7c8e65c9c3 Mon Sep 17 00:00:00 2001 From: Enrico Molino Date: Mon, 11 May 2026 15:14:28 +0200 Subject: [PATCH 2/8] ci: upgrade org.owasp.dependencycheck to 12.2.2 Fixes CI failure caused by CVE-2026-6785/6786 whose NVD reference URLs exceed the VARCHAR(1000) column limit in the plugin's H2 database schema. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ea53f4195..d04d1fe97 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id "io.github.gradle-nexus.publish-plugin" version "1.3.0" - id "org.owasp.dependencycheck" version "12.1.3" + id "org.owasp.dependencycheck" version "12.2.2" } ext.projectVersion = '3.3.0-SNAPSHOT' From 2cd9c9b3758ef4ae3bd24575fd972afc652bb8eb Mon Sep 17 00:00:00 2001 From: Enrico Molino Date: Mon, 11 May 2026 15:50:45 +0200 Subject: [PATCH 3/8] fix: enforce agent-before-pod codegen order to preserve SystemApi health methods --- symphony-bdk-core/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/symphony-bdk-core/build.gradle b/symphony-bdk-core/build.gradle index 19edaae5d..fce96e7c5 100644 --- a/symphony-bdk-core/build.gradle +++ b/symphony-bdk-core/build.gradle @@ -132,3 +132,5 @@ apisToGenerate.each { api, path -> // Duplicated AuthRequest class, we need the one from auth API, so task order matters here tasks.generateAuth.dependsOn tasks.generateLogin +// Duplicated SystemApi class, we need the one from agent API (contains v3Health/v3ExtendedHealth), so task order matters here +tasks.generatePod.dependsOn tasks.generateAgent From 836e0d8cf9843acbe9b64848022902cc028721a9 Mon Sep 17 00:00:00 2001 From: Enrico Molino Date: Mon, 11 May 2026 19:33:49 +0200 Subject: [PATCH 4/8] Update build.gradle --- buildSrc/build.gradle | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 121fcb961..8e9979c5a 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -11,3 +11,16 @@ dependencies { implementation 'de.undercouch:gradle-download-task:5.0.2' implementation 'com.github.ben-manes:gradle-versions-plugin:0.42.0' } + +configurations.all { + resolutionStrategy { + // openapi-generator 6.6.0 ships jackson-databind 2.14.0 which is missing NativeImageUtil.isInNativeImage(), + // required by owasp-dependencycheck 12.2.2+ via parent classloader delegation. + // Pin jackson-dataformat-yaml and snakeyaml explicitly to prevent collateral upgrades. + force 'com.fasterxml.jackson.core:jackson-databind:2.18.2' + force 'com.fasterxml.jackson.core:jackson-core:2.18.2' + force 'com.fasterxml.jackson.core:jackson-annotations:2.18.2' + force 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.14.0' + force 'org.yaml:snakeyaml:1.33' + } +} From 95c8f79d6addd486d4ebd1e4291b722136a81ff0 Mon Sep 17 00:00:00 2001 From: Enrico Molino Date: Mon, 11 May 2026 20:26:25 +0200 Subject: [PATCH 5/8] ci: set failOnError=false on dependencyCheck to tolerate OWASP 12.2.2 JAR analysis bugs --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index d04d1fe97..bc2a5762f 100644 --- a/build.gradle +++ b/build.gradle @@ -61,4 +61,5 @@ repositories { dependencyCheck { failBuildOnCVSS=5 suppressionFile="./allow-list.xml" + failOnError=false } From f337ba6ae9bb252fd48172eff35ec4d6deaf948f Mon Sep 17 00:00:00 2001 From: Enrico Molino Date: Mon, 11 May 2026 22:23:18 +0200 Subject: [PATCH 6/8] ci: force commons-lang3/commons-io/slf4j/guava in buildSrc to fix OWASP classloader conflicts --- buildSrc/build.gradle | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 8e9979c5a..9d612f708 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -14,13 +14,18 @@ dependencies { configurations.all { resolutionStrategy { - // openapi-generator 6.6.0 ships jackson-databind 2.14.0 which is missing NativeImageUtil.isInNativeImage(), - // required by owasp-dependencycheck 12.2.2+ via parent classloader delegation. - // Pin jackson-dataformat-yaml and snakeyaml explicitly to prevent collateral upgrades. + // owasp-dependencycheck 12.2.2 requires newer versions of several libraries than openapi-generator 6.6.0 + // provides. Because buildSrc's classpath is the parent classloader for all plugin classloaders, OWASP + // inherits buildSrc's older versions via parent-first delegation and fails with NoSuchMethodError. + // Force all conflicting libraries to the versions OWASP 12.2.2 requires. force 'com.fasterxml.jackson.core:jackson-databind:2.18.2' force 'com.fasterxml.jackson.core:jackson-core:2.18.2' force 'com.fasterxml.jackson.core:jackson-annotations:2.18.2' force 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.14.0' force 'org.yaml:snakeyaml:1.33' + force 'org.apache.commons:commons-lang3:3.20.0' + force 'commons-io:commons-io:2.22.0' + force 'org.slf4j:slf4j-api:2.0.17' + force 'com.google.guava:guava:33.6.0-jre' } } From 2b7487d78837d6240218d3532e6e6a50b894b367 Mon Sep 17 00:00:00 2001 From: Enrico Molino Date: Tue, 12 May 2026 11:44:30 +0200 Subject: [PATCH 7/8] chore(deps): bump Spring Boot/log4j/netty/handlebars to clear CVE-gated scan Bumps in symphony-bdk-bom so dependencyCheckAggregate stays under the CVSS-5 fail gate now that OWASP 12.2.2 analysis runs to completion: - spring-boot-dependencies 3.5.11 -> 3.5.14 (pulls spring-framework 6.2.18, spring-security 6.5.10, tomcat-embed 10.1.54) - log4j-bom 2.24.2 -> 2.26.0 - netty-bom 4.1.133.Final added to override Spring Boot's 4.1.132 (still vulnerable to CVE-2026-41417) - handlebars 4.3.1 -> 4.5.1 (picks up commons-lang3 3.18.0 fix for CVE-2025-48924) Adds two narrow allow-list.xml suppressions for known false positives: kotlin-stdlib CVE-2020-29582 (fixed in 1.4.21; CPE overmatches all 1.x) and the handlebars-v4.7.7.js bundled-resource CVEs (JS engine not used by symphony-bdk-template-handlebars). --- allow-list.xml | 24 ++++++++++++++++++++++++ symphony-bdk-bom/build.gradle | 8 +++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/allow-list.xml b/allow-list.xml index 7af26b842..bce70d1e4 100644 --- a/allow-list.xml +++ b/allow-list.xml @@ -15,4 +15,28 @@ com.jayway.jsonpath:json-path:2.8.0 CVE-2023-51074 + + + ^pkg:maven/org\.jetbrains\.kotlin/kotlin-stdlib(-jdk7|-jdk8|-common)?@.*$ + CVE-2020-29582 + + + + ^pkg:javascript/handlebars@.*$ + CVE-2026-33916 + CVE-2026-33937 + CVE-2026-33938 + CVE-2026-33939 + CVE-2026-33940 + CVE-2026-33941 + GHSA-7rx3-28cr-v5wh + GHSA-442j-39wm-28r2 + diff --git a/symphony-bdk-bom/build.gradle b/symphony-bdk-bom/build.gradle index c9eef1876..577b909d0 100644 --- a/symphony-bdk-bom/build.gradle +++ b/symphony-bdk-bom/build.gradle @@ -16,13 +16,15 @@ repositories { dependencies { // import Spring Boot's BOM - api platform('org.springframework.boot:spring-boot-dependencies:3.5.11') + api platform('org.springframework.boot:spring-boot-dependencies:3.5.14') // import Jackson's BOM api platform('com.fasterxml.jackson:jackson-bom:2.18.2') // import Jersey's BOM api platform('org.glassfish.jersey:jersey-bom:3.1.9') // import Log4j's BOM - api platform('org.apache.logging.log4j:log4j-bom:2.24.2') + api platform('org.apache.logging.log4j:log4j-bom:2.26.0') + // override Netty (Spring Boot 3.5.14 ships 4.1.132 which is still vulnerable to CVE-2026-41417) + api platform('io.netty:netty-bom:4.1.133.Final') // define all our dependencies versions constraints { @@ -69,7 +71,7 @@ dependencies { api 'org.projectreactor:reactor-spring:1.0.1.RELEASE' api 'org.freemarker:freemarker:2.3.33' - api 'com.github.jknack:handlebars:4.3.1' + api 'com.github.jknack:handlebars:4.5.1' api 'org.reflections:reflections:0.10.2' api 'com.tngtech.archunit:archunit-junit5:1.2.1' From 9287e1fe4edfaaba3df6abdd2386e96eda714e29 Mon Sep 17 00:00:00 2001 From: Enrico Molino Date: Tue, 12 May 2026 14:08:52 +0200 Subject: [PATCH 8/8] ci: remove failOnError=false now that OWASP analyzer crash is fixed The buildSrc classloader fix (f337ba6a) made the analyzer run to completion, so the tolerance flag added in 95c8f79d is no longer needed. Reverting to the default (true) so a future analyzer regression fails loudly instead of silently passing with an incomplete report. --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index bc2a5762f..d04d1fe97 100644 --- a/build.gradle +++ b/build.gradle @@ -61,5 +61,4 @@ repositories { dependencyCheck { failBuildOnCVSS=5 suppressionFile="./allow-list.xml" - failOnError=false }