quarkusio/quarkus · error · SpiffeConnectionException

Leaf certificate is missing the key usage extension

Error message

Leaf certificate is missing the key usage extension

What it means

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.

Source

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

final class SpiffeValidator {

    private static final String SPIFFE_URI_PREFIX = "spiffe://";
    private static final int URI_SAN_TYPE = 6;
    private static final int MAX_SPIFFE_ID_LENGTH = 2048;
    private static final int MAX_TRUST_DOMAIN_LENGTH = 255;

    private SpiffeValidator() {
    }

    static String validateLeaf(X509Certificate leaf) throws SpiffeConnectionException {
        if (leaf.getBasicConstraints() != -1) {
            throw new SpiffeConnectionException("Leaf certificate must not have CA flag set to true");
        }

        boolean[] keyUsage = leaf.getKeyUsage();
        if (keyUsage == null) {
            throw new SpiffeConnectionException("Leaf certificate is missing the key usage extension");
        }
        if (keyUsage.length < 1 || !keyUsage[0]) {
            throw new SpiffeConnectionException("Leaf certificate must have 'digitalSignature' as key usage");
        }
        if (keyUsage.length > 5 && keyUsage[5]) {
            throw new SpiffeConnectionException("Leaf certificate must not have 'keyCertSign' as key usage");
        }
        if (keyUsage.length > 6 && keyUsage[6]) {
            throw new SpiffeConnectionException("Leaf certificate must not have 'cRLSign' as key usage");
        }

        return extractAndValidateUriSan(leaf);
    }

    // X.509-SVID 3.2 SHOULD: signing cert SHOULD itself be an SVID (not enforced — upstream CA may not be SPIFFE-aware)
    // 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)
    static void validateIntermediate(X509Certificate cert) throws SpiffeConnectionException {
        if (cert.getBasicConstraints() < 0) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Regenerate test certificates including the extension: -addext "keyUsage=digitalSignature,keyEncipherment".
  2. Verify the agent's upstream CA issues properly extended SVIDs (openssl x509 -noout -text).
  3. If building chains in tests, add KeyUsage and BasicConstraints extensions explicitly.
  4. Treat the error as non-retryable; fix the certificate issuer, not the client.

Example fix

// before
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -nodes
// after
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -nodes \
  -addext "keyUsage=digitalSignature,keyEncipherment"
Defensive patterns

Strategy: validation

Validate before calling

static boolean hasKeyUsage(X509Certificate leaf) {
    return leaf.getKeyUsage() != null && leaf.getKeyUsage().length > 0;
}

Type guard

static boolean hasDigitalSignature(X509Certificate cert) {
    boolean[] ku = cert.getKeyUsage();
    return ku != null && ku.length > 0 && ku[0];
}

Try / catch

try {
    SpiffeValidator.validateLeaf(leaf);
} catch (SpiffeConnectionException e) {
    throw new CertificateException("Leaf lacks required KeyUsage extension: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: 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.

Common situations: Custom SPIRE or test upstream CAs issuing minimal certificates; hand-rolled certificate generation in tests missing extensions; openssl-generated certs without -addext keyUsage.

Understand the failure class

Related errors


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