quarkusio/quarkus · critical · SpiffeConnectionException

Leaf certificate must not have CA flag set to true

Error message

Leaf certificate must not have CA flag set to true

What it means

When validating a fetched X.509 SVID, the leaf certificate must be an end-entity certificate. If the leaf has the BasicConstraints CA extension set (getBasicConstraints() != -1), it is a CA certificate and cannot be used as a workload identity, so the validator throws SpiffeConnectionException. The SPIRE agent should never hand out such a chain; seeing this means the identity material is wrong or spoofed.

Source

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

import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import io.quarkus.spiffe.client.SpiffeConnectionException;

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);
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Inspect the served chain with openssl x509 -noout -text and confirm the leaf has CA:FALSE.
  2. Restart/redeploy the SPIRE agent and re-fetch SVIDs; verify with spire-agent api fetch x509.
  3. Ensure you are not swapping the trust bundle (CA certs) and the SVID chain in custom code.
  4. Catch SpiffeConnectionException and treat it as non-retryable security misconfiguration.

Example fix

// before
X509Certificate leaf = chain.get(0);
String spiffeId = SpiffeValidator.validateLeaf(leaf); // throws if leaf is a CA
// after
X509Certificate leaf = chain.get(0);
if (leaf.getBasicConstraints() != -1) {
    throw new IllegalStateException("Fetched leaf is a CA certificate; check SPIRE agent registration entries");
}
String spiffeId = SpiffeValidator.validateLeaf(leaf);
Defensive patterns

Strategy: validation

Validate before calling

static boolean isEndEntity(X509Certificate leaf) {
    try {
        return leaf.getBasicConstraints() == -1;
    } catch (CertificateParsingException e) {
        return false;
    }
}

Type guard

static boolean isLeafNotCa(X509Certificate cert) {
    return cert != null && cert.getBasicConstraints() == -1;
}

Try / catch

try {
    String id = SpiffeValidator.validateLeaf(leaf);
} catch (SpiffeConnectionException e) {
    // non-retryable: identity material is invalid
    throw new SecurityException("SPIRE served a CA certificate as leaf: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Calling the SVID validation path (used when trusting fetched certificates for mTLS) with a chain whose first certificate carries CA=true, e.g. an agent serving an intermediate/CA cert as the leaf.

Common situations: A misbehaving or compromised SPIRE agent; custom test agents emitting wrong chains; manually constructed trust material being fed through the validator; mixing up bundle (CA) and SVID (leaf) chains in custom code paths.

Understand the failure class

Related errors


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