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
- Inspect the served chain with openssl x509 -noout -text and confirm the leaf has CA:FALSE.
- Restart/redeploy the SPIRE agent and re-fetch SVIDs; verify with spire-agent api fetch x509.
- Ensure you are not swapping the trust bundle (CA certs) and the SVID chain in custom code.
- 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
- Never pass trust-bundle/CA certs through the leaf validation path
- Verify served chains with openssl (CA:FALSE on leaf)
- Use genuine SPIRE agents; avoid hand-rolled test chains in prod paths
- Treat this error as a security incident, not a transient fault
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
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Leaf certificate is missing the key usage extension
- Leaf certificate must not have 'keyCertSign' as key usage
- Leaf certificate must not have 'cRLSign' as key usage
- X.509-SVID response from SPIRE agent contains no SVIDs
- X.509-SVID response from SPIRE agent has empty certificate c
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/891079909c6cd8b4.
Report an issue: GitHub.