{"record":{"id":"143b5cd5da69f268","repo":"quarkusio/quarkus","slug":"leaf-certificate-has-no-subject-alternative-names","errorCode":null,"errorMessage":"Leaf certificate has no Subject Alternative Names","messagePattern":"Leaf certificate has no Subject Alternative Names","errorType":"exception","errorClass":"SpiffeConnectionException","httpStatus":null,"severity":"error","filePath":"extensions/spiffe-client/runtime/src/main/java/io/quarkus/spiffe/client/runtime/internal/SpiffeValidator.java","lineNumber":167,"sourceCode":"            if (sans == null) {\n                return null;\n            }\n            for (var san : sans) {\n                if (san.size() > 1 && san.get(0) instanceof Integer type && type == URI_SAN_TYPE\n                        && san.get(1) != null) {\n                    return san.get(1).toString();\n                }\n            }\n        } catch (Exception ignored) {\n        }\n        return null;\n    }\n\n    private static String extractAndValidateUriSan(X509Certificate leaf) throws SpiffeConnectionException {\n        try {\n            var sans = leaf.getSubjectAlternativeNames();\n            if (sans == null || sans.isEmpty()) {\n                throw new SpiffeConnectionException(\"Leaf certificate has no Subject Alternative Names\");\n            }\n            List<String> uriSans = new ArrayList<>();\n            for (var san : sans) {\n                if (san.size() > 1 && san.get(0) instanceof Integer type && type == URI_SAN_TYPE\n                        && san.get(1) != null) {\n                    uriSans.add(san.get(1).toString());\n                }\n            }\n            if (uriSans.isEmpty()) {\n                throw new SpiffeConnectionException(\"Leaf certificate has no URI Subject Alternative Names\");\n            }\n            if (uriSans.size() > 1) {\n                throw new SpiffeConnectionException(\n                        \"Leaf certificate must contain exactly one URI SAN, found \" + uriSans.size() + \": \" + uriSans);\n            }\n            return uriSans.get(0);\n        } catch (SpiffeConnectionException e) {\n            throw e;","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/spiffe-client/runtime/src/main/java/io/quarkus/spiffe/client/runtime/internal/SpiffeValidator.java#L149-L185","documentation":"The leaf (workload) certificate presented by the SPIFFE server/workload has no Subject Alternative Names extension at all. SPIFFE identity is carried exclusively in URI SANs, so a leaf without any SAN cannot carry an identity and is rejected. This indicates a broken or non-SPIFFE certificate.","triggerScenarios":"validateLeaf -> extractAndValidateUriSan is invoked during TLS trust-bundle/certificate validation when X509Certificate.getSubjectAlternativeNames() returns null or an empty collection for the leaf certificate.","commonSituations":"A server presents a plain TLS certificate (e.g. a default self-signed or corporate CA cert) instead of a SPIFFE workload cert; a CA issues certificates without the SAN extension due to a misconfigured certificate template.","solutions":["Ensure the endpoint presents a SPIFFE X.509 SVID certificate that includes the URI SAN extension.","Fix the certificate-issuing template at the SPIFFE CA (e.g. SPIRE) so leaf SVIDs always include a URI SAN.","Verify you are connecting to the intended SPIFFE-authenticated service, not a different TLS endpoint on the same port."],"exampleFix":"// before: certificate profile without SAN\n//   openssl req -new -key key.pem -out csr.csr  (CN only)\n// after: SPIFFE SVID profile\n//   subjectAltName = URI:spiffe://trust.domain/ns/default/sa/app","handlingStrategy":"validation","validationCode":"boolean hasSan(X509Certificate cert) throws Exception {\n    var sans = cert.getSubjectAlternativeNames();\n    return sans != null && !sans.isEmpty();\n}","typeGuard":null,"tryCatchPattern":"try {\n    validator.validateLeaf(chain);\n} catch (SpiffeConnectionException e) {\n    throw new IllegalStateException(\"Endpoint did not present a valid SPIFFE SVID: \" + e.getMessage(), e);\n}","preventionTips":["Verify SVIDs with openssl before deployment: openssl x509 -text -noout | grep -A2 'Alternative'.","Ensure the SPIRE server/CA profile always includes the SAN extension.","Confirm the client connects to the SPIFFE-enabled endpoint, not a plain TLS service."],"tags":["spiffe","certificate","tls","x509"],"backgroundTag":"certificate-missing-san","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}