{"record":{"id":"ef99f7d733d2ed18","repo":"quarkusio/quarkus","slug":"leaf-certificate-must-have-digitalsignature-as-k","errorCode":null,"errorMessage":"Leaf certificate must have 'digitalSignature' as key usage","messagePattern":"Leaf certificate must have 'digitalSignature' as key usage","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":30,"sourceCode":"    private static final String SPIFFE_URI_PREFIX = \"spiffe://\";\n    private static final int URI_SAN_TYPE = 6;\n    private static final int MAX_SPIFFE_ID_LENGTH = 2048;\n    private static final int MAX_TRUST_DOMAIN_LENGTH = 255;\n\n    private SpiffeValidator() {\n    }\n\n    static String validateLeaf(X509Certificate leaf) throws SpiffeConnectionException {\n        if (leaf.getBasicConstraints() != -1) {\n            throw new SpiffeConnectionException(\"Leaf certificate must not have CA flag set to true\");\n        }\n\n        boolean[] keyUsage = leaf.getKeyUsage();\n        if (keyUsage == null) {\n            throw new SpiffeConnectionException(\"Leaf certificate is missing the key usage extension\");\n        }\n        if (keyUsage.length < 1 || !keyUsage[0]) {\n            throw new SpiffeConnectionException(\"Leaf certificate must have 'digitalSignature' as key usage\");\n        }\n        if (keyUsage.length > 5 && keyUsage[5]) {\n            throw new SpiffeConnectionException(\"Leaf certificate must not have 'keyCertSign' as key usage\");\n        }\n        if (keyUsage.length > 6 && keyUsage[6]) {\n            throw new SpiffeConnectionException(\"Leaf certificate must not have 'cRLSign' as key usage\");\n        }\n\n        return extractAndValidateUriSan(leaf);\n    }\n\n    // X.509-SVID 3.2 SHOULD: signing cert SHOULD itself be an SVID (not enforced — upstream CA may not be SPIFFE-aware)\n    // X.509-SVID 3.2 SHOULD: signing cert SHOULD reside in the trust domain of leaf SVIDs it issues (not enforced — cross-domain signing is allowed)\n    static void validateIntermediate(X509Certificate cert) throws SpiffeConnectionException {\n        if (cert.getBasicConstraints() < 0) {\n            throw new SpiffeConnectionException(\n                    \"Signing certificate must have CA flag set to true: \" + cert.getSubjectX500Principal());\n        }","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/spiffe-client/runtime/src/main/java/io/quarkus/spiffe/client/runtime/internal/SpiffeValidator.java#L12-L48","documentation":"The leaf's KeyUsage extension must include the digitalSignature bit, since workload certificates are used to sign TLS handshakes and JWTs. If the extension exists but bit 0 is unset (or the array is empty), the validator rejects the certificate. Without digitalSignature the certificate cannot be used for the mTLS the extension establishes.","triggerScenarios":"Validation encountering a leaf whose KeyUsage is present but does not assert digitalSignature — typically from hand-generated certificates with only keyEncipherment, keyAgreement, or nonRepudiation.","commonSituations":"Certificates created with keyUsage=keyEncipherment only; templates from internal PKIs copied for SPIFFE tests; tooling defaults that omit digitalSignature.","solutions":["Reissue the certificate including digitalSignature in keyUsage (openssl -addext \"keyUsage=digitalSignature,...\").","Use a proper test CA (e.g. cfssl or SPIRE's own tooling) that emits SPIFFE-compliant SVIDs.","Inspect the cert: openssl x509 -noout -ext keyUsage and confirm Digital Signature is listed.","If using a custom upstream CA, update its certificate template."],"exampleFix":"// before\n-addext \"keyUsage=keyEncipherment\"\n// after\n-addext \"keyUsage=digitalSignature,keyEncipherment\"","handlingStrategy":"validation","validationCode":"static boolean hasDigitalSignature(X509Certificate leaf) {\n    boolean[] ku = leaf.getKeyUsage();\n    return ku != null && ku.length > 0 && ku[0];\n}","typeGuard":"static boolean isSignCapableLeaf(X509Certificate cert) {\n    boolean[] ku = cert.getKeyUsage();\n    return ku != null && ku.length > 0 && ku[0];\n}","tryCatchPattern":"try {\n    SpiffeValidator.validateLeaf(leaf);\n} catch (SpiffeConnectionException e) {\n    throw new CertificateException(\"Leaf cannot sign (missing digitalSignature): \" + e.getMessage(), e);\n}","preventionTips":["Always include digitalSignature in workload cert keyUsage templates","Audit internal PKI templates reused for SPIFFE testing","Validate locally with openssl x509 -noout -ext keyUsage before wiring tests","Reissue certs rather than attempting client-side workarounds"],"tags":["spiffe","x509","keyusage","digital-signature"],"backgroundTag":"invalid-certificate-chain","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}