quarkusio/quarkus · error · SpiffeConnectionException

Leaf certificate must contain exactly one URI SAN, found

Error message

Leaf certificate must contain exactly one URI SAN, found 

What it means

SPIFFE X.509 SVIDs must contain exactly one URI SAN. The leaf certificate carries multiple URI SANs, which violates the SPIFFE specification, so the validator refuses it because the identity would be ambiguous.

Source

Thrown at extensions/spiffe-client/runtime/src/main/java/io/quarkus/spiffe/client/runtime/internal/SpiffeValidator.java:180

    private static String extractAndValidateUriSan(X509Certificate leaf) throws SpiffeConnectionException {
        try {
            var sans = leaf.getSubjectAlternativeNames();
            if (sans == null || sans.isEmpty()) {
                throw new SpiffeConnectionException("Leaf certificate has no Subject Alternative Names");
            }
            List<String> uriSans = new ArrayList<>();
            for (var san : sans) {
                if (san.size() > 1 && san.get(0) instanceof Integer type && type == URI_SAN_TYPE
                        && san.get(1) != null) {
                    uriSans.add(san.get(1).toString());
                }
            }
            if (uriSans.isEmpty()) {
                throw new SpiffeConnectionException("Leaf certificate has no URI Subject Alternative Names");
            }
            if (uriSans.size() > 1) {
                throw new SpiffeConnectionException(
                        "Leaf certificate must contain exactly one URI SAN, found " + uriSans.size() + ": " + uriSans);
            }
            return uriSans.get(0);
        } catch (SpiffeConnectionException e) {
            throw e;
        } catch (Exception e) {
            throw new SpiffeConnectionException("Failed to extract URI SAN from leaf certificate", e);
        }
    }

    private static boolean isValidTrustDomainChar(char c) {
        return (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '-' || c == '_';
    }

    private static boolean isValidPathChar(char c) {
        return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')
                || c == '.' || c == '-' || c == '_';
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Re-issue the leaf certificate with a single URI SAN containing the workload's SPIFFE ID.
  2. Fix the CA/issuance code that appends multiple URI SANs to one certificate.
  3. If multiple identities are needed, issue separate SVIDs rather than packing them into one certificate.

Example fix

// before
//   subjectAltName = URI:spiffe://td/sa/a, URI:spiffe://td/sa/b
// after
//   subjectAltName = URI:spiffe://td/sa/a
Defensive patterns

Strategy: validation

Validate before calling

long uriSanCount(X509Certificate cert) throws Exception {
    var sans = cert.getSubjectAlternativeNames();
    if (sans == null) return 0;
    return sans.stream().filter(s -> s.size() > 1 && Integer.valueOf(6).equals(s.get(0))).count();
}

Try / catch

try {
    validator.validateLeaf(chain);
} catch (SpiffeConnectionException e) {
    throw new IllegalStateException("SVID must contain exactly one URI SAN: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: extractAndValidateUriSan finds uriSans.size() > 1 while validating the leaf certificate during validateLeaf.

Common situations: Custom CAs issuing certificates that bundle several identities in one cert; concatenating SAN lists in certificate templates; old tooling that adds both a service and host URI SAN.

Understand the failure class

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/ebec91c4b6cbad45. Report an issue: GitHub.