From 762a1405df21db63c638d9a5099a7dd80f0fac00 Mon Sep 17 00:00:00 2001 From: hidingmyname Date: Tue, 3 Nov 2026 15:27:15 +0800 Subject: [PATCH] core: Validate trust domain names in SPIFFE bundle map files loadTrustBundleFromFile used the trust_domains keys as they were. A key that is not a valid SPIFFE trust domain name, such as UPPER.example.com or invalid#character, was loaded but could never match a peer, because the peer's trust domain always comes from SpiffeUtil.parse() and is valid and lower case. The javadoc and gRFC A87 say that an invalid entry makes the whole bundle map invalid. Validate each key with the existing validateTrustDomain(), as grpc-go does. Fixes #13154 --- .../main/java/io/grpc/internal/SpiffeUtil.java | 1 + .../java/io/grpc/internal/SpiffeUtilTest.java | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/core/src/main/java/io/grpc/internal/SpiffeUtil.java b/core/src/main/java/io/grpc/internal/SpiffeUtil.java index 102485ebd54..e8f68a348ce 100644 --- a/core/src/main/java/io/grpc/internal/SpiffeUtil.java +++ b/core/src/main/java/io/grpc/internal/SpiffeUtil.java @@ -170,6 +170,7 @@ public static SpiffeBundle loadTrustBundleFromFile(String trustBundleFile) throw Map> trustBundleMap = new HashMap<>(); Map sequenceNumbers = new HashMap<>(); for (String trustDomainName : trustDomainsNode.keySet()) { + validateTrustDomain(trustDomainName); Map domainNode = JsonUtil.getObject(trustDomainsNode, trustDomainName); if (domainNode.size() == 0) { trustBundleMap.put(trustDomainName, Collections.emptyList()); diff --git a/core/src/test/java/io/grpc/internal/SpiffeUtilTest.java b/core/src/test/java/io/grpc/internal/SpiffeUtilTest.java index bea79704c66..a115116bb9e 100644 --- a/core/src/test/java/io/grpc/internal/SpiffeUtilTest.java +++ b/core/src/test/java/io/grpc/internal/SpiffeUtilTest.java @@ -32,6 +32,7 @@ import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; +import java.nio.charset.StandardCharsets; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Collection; @@ -419,6 +420,21 @@ public void loadTrustBundleFromFileFailureTest() { + DOMAIN_ERROR_MESSAGE, iae.getMessage()); } + @Test + public void loadTrustBundleFromFileInvalidTrustDomainTest() throws Exception { + for (String trustDomain : new String[] {"invalid#character", "UPPER.example.com"}) { + File bundleFile = tempFolder.newFile(); + try (OutputStream fileStream = new FileOutputStream(bundleFile)) { + fileStream.write(("{\"trust_domains\": {\"" + trustDomain + "\": {}}}") + .getBytes(StandardCharsets.UTF_8)); + } + IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, + () -> SpiffeUtil.loadTrustBundleFromFile(bundleFile.toString())); + assertEquals("Trust Domain must contain only letters, numbers, dots, dashes, and " + + "underscores ([a-z0-9.-_])", iae.getMessage()); + } + } + @Test public void loadTrustBundleFromFileParameterValidityTest() { NullPointerException npe = assertThrows(NullPointerException.class, () -> SpiffeUtil