{"record":{"id":"e4f301fcfaafe832","repo":"quarkusio/quarkus","slug":"leaf-certificate-must-not-have-keycertsign-as-ke","errorCode":null,"errorMessage":"Leaf certificate must not have 'keyCertSign' as key usage","messagePattern":"Leaf certificate must not have 'keyCertSign' as key usage","errorType":"exception","errorClass":"SpiffeConnectionException","httpStatus":null,"severity":"critical","filePath":"extensions/spiffe-client/runtime/src/main/java/io/quarkus/spiffe/client/runtime/internal/SpiffeValidator.java","lineNumber":33,"sourceCode":"    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        }\n        boolean[] keyUsage = cert.getKeyUsage();\n        if (keyUsage == null || keyUsage.length <= 5 || !keyUsage[5]) {\n            throw new SpiffeConnectionException(","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/spiffe-client/runtime/src/main/java/io/quarkus/spiffe/client/runtime/internal/SpiffeValidator.java#L15-L51","documentation":"A leaf workload certificate must not be able to sign other certificates. If KeyUsage includes the keyCertSign bit, the certificate could act as a CA and the validator rejects it to enforce the SPIFFE X.509-SVID profile. This protects against privilege escalation if the workload's key is compromised.","triggerScenarios":"Validation encountering a leaf whose KeyUsage asserts keyCertSign (bit 5), e.g. a self-signed CA certificate or an intermediate passed in as the leaf.","commonSituations":"Testing with self-signed CA certs as if they were SVIDs; upstream CA templates leaking CA usages into workload certs; accidentally passing a bundle/intermediate where a leaf is expected.","solutions":["Serve a proper end-entity SVID without CA flags or CA usages from the SPIRE agent.","Check the leaf: openssl x509 -noout -ext keyUsage — remove keyCertSign from workload cert templates.","Separate your CA chain (trust bundle) from the leaf chain in custom code paths.","Verify SPIRE server registration entries map to workload profiles, not CA profiles."],"exampleFix":"// before\n-addext \"keyUsage=digitalSignature,keyCertSign\"\n// after\n-addext \"keyUsage=digitalSignature,keyEncipherment\"","handlingStrategy":"validation","validationCode":"static boolean lacksKeyCertSign(X509Certificate leaf) {\n    boolean[] ku = leaf.getKeyUsage();\n    return ku == null || ku.length <= 5 || !ku[5];\n}","typeGuard":"static boolean isNotCaCapable(X509Certificate cert) {\n    boolean[] ku = cert.getKeyUsage();\n    return cert.getBasicConstraints() == -1 && (ku == null || ku.length <= 5 || !ku[5]);\n}","tryCatchPattern":"try {\n    SpiffeValidator.validateLeaf(leaf);\n} catch (SpiffeConnectionException e) {\n    throw new SecurityException(\"Leaf must not have keyCertSign usage: \" + e.getMessage(), e);\n}","preventionTips":["Never feed CA/intermediate certificates into leaf validation","Strip CA usages from workload certificate templates","Separate trust-bundle handling from SVID-chain handling in custom code","Confirm SPIRE registration entries issue end-entity profiles"],"tags":["spiffe","x509","keyusage","keycertsign","certificate-validation"],"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"}