{"record":{"id":"029069390ba9fb14","repo":"quarkusio/quarkus","slug":"leaf-certificate-is-missing-the-key-usage-extensio","errorCode":null,"errorMessage":"Leaf certificate is missing the key usage extension","messagePattern":"Leaf certificate is missing the key usage extension","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":27,"sourceCode":"\nfinal class SpiffeValidator {\n\n    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) {","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/spiffe-client/runtime/src/main/java/io/quarkus/spiffe/client/runtime/internal/SpiffeValidator.java#L9-L45","documentation":"A valid workload leaf certificate must carry the X.509 KeyUsage extension. When getKeyUsage() returns null the extension is absent, so the validator cannot confirm the certificate is fit for signing and throws SpiffeConnectionException. SPIRE-issued SVIDs always include KeyUsage, so its absence signals non-standard or corrupted material.","triggerScenarios":"Validation path encountering a leaf without the KeyUsage OID (2.5.29.15), e.g. certificates generated by a custom/test CA without extensions or a corrupted agent response.","commonSituations":"Custom SPIRE or test upstream CAs issuing minimal certificates; hand-rolled certificate generation in tests missing extensions; openssl-generated certs without -addext keyUsage.","solutions":["Regenerate test certificates including the extension: -addext \"keyUsage=digitalSignature,keyEncipherment\".","Verify the agent's upstream CA issues properly extended SVIDs (openssl x509 -noout -text).","If building chains in tests, add KeyUsage and BasicConstraints extensions explicitly.","Treat the error as non-retryable; fix the certificate issuer, not the client."],"exampleFix":"// before\nopenssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -nodes\n// after\nopenssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -nodes \\\n  -addext \"keyUsage=digitalSignature,keyEncipherment\"","handlingStrategy":"validation","validationCode":"static boolean hasKeyUsage(X509Certificate leaf) {\n    return leaf.getKeyUsage() != null && leaf.getKeyUsage().length > 0;\n}","typeGuard":"static boolean hasDigitalSignature(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 lacks required KeyUsage extension: \" + e.getMessage(), e);\n}","preventionTips":["Generate test certs with -addext keyUsage=digitalSignature,...","Use SPIRE-compliant tooling (cfssl, spire test CAs) for local chains","Inspect issued certs with openssl x509 -noout -ext keyUsage","Keep upstream CA templates aligned with the SPIFFE X.509-SVID profile"],"tags":["spiffe","x509","keyusage","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"}