hyperledger/fabric · critical

CA Certificate did not have the CA attribute, (SN: %x)

Error message

CA Certificate did not have the CA attribute, (SN: %x)

What it means

finalizeSetupCAs validates that every root and intermediate CA identity's certificate has the BasicConstraints CA flag set (cert.IsCA). A certificate in cacerts/ or intermediatecerts/ without CA:true is rejected because it cannot properly sign or validate chains.

Source

Thrown at msp/mspimplsetup.go:255

			crl.SignatureValue = asn1.BitString{Bytes: sig, BitLength: 8 * len(sig)}
		}

		// TODO: pre-verify the signature on the CRL and create a map
		//       of CA certs to respective CRLs so that later upon
		//       validation we can already look up the CRL given the
		//       chain of the certificate to be validated

		msp.CRL[i] = crl
	}

	return nil
}

func (msp *bccspmsp) finalizeSetupCAs() error {
	// ensure that our CAs are properly formed and that they are valid
	for _, id := range append(append([]Identity{}, msp.rootCerts...), msp.intermediateCerts...) {
		if !id.(*identity).cert.IsCA {
			return errors.Errorf("CA Certificate did not have the CA attribute, (SN: %x)", id.(*identity).cert.SerialNumber)
		}
		if _, err := getSubjectKeyIdentifierFromCert(id.(*identity).cert); err != nil {
			return errors.WithMessagef(err, "CA Certificate problem with Subject Key Identifier extension, (SN: %x)", id.(*identity).cert.SerialNumber)
		}

		if err := msp.validateCAIdentity(id.(*identity)); err != nil {
			return errors.WithMessagef(err, "CA Certificate is not valid, (SN: %s)", id.(*identity).cert.SerialNumber)
		}
	}

	// populate certificationTreeInternalNodesMap to mark the internal nodes of the
	// certification tree
	msp.certificationTreeInternalNodesMap = make(map[string]bool)
	for _, id := range append([]Identity{}, msp.intermediateCerts...) {
		chain, err := msp.getUniqueValidationChain(id.(*identity).cert, msp.getValidityOptsForCert(id.(*identity).cert))
		if err != nil {
			return errors.WithMessagef(err, "failed getting validation chain, (SN: %s)", id.(*identity).cert.SerialNumber)
		}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Replace the certificate in cacerts/intermediatecerts with a real CA certificate that has basicConstraints CA:TRUE
  2. Re-generate the CA with openssl req -x509 (which sets CA:true) or fabric-ca-server init
  3. Check with: openssl x509 -in cert.pem -text | grep -A1 'Basic Constraints'
  4. If intending an intermediate CA, issue it from the root with CA:TRUE extension

Example fix

// before: leaf cert (CA:FALSE) in msp/cacerts/
// after: proper CA cert
//   openssl req -x509 -new -nodes -key ca.key -sha256 -days 365 \
//     -subj '/CN=Org1 CA' -addext 'basicConstraints=critical,CA:TRUE' -out ca.crt
null
Defensive patterns

Strategy: validation

Validate before calling

for _, c := range caCerts {
    if !c.IsCA {
        return fmt.Errorf("cert %s lacks CA basic constraint", c.Subject)
    }
    if c.KeyUsage&x509.KeyUsageCertSign == 0 {
        return fmt.Errorf("cert %s lacks certSign key usage", c.Subject)
    }
}

Type guard

func isCACert(c *x509.Certificate) bool {
    return c.IsCA && c.KeyUsage&x509.KeyUsageCertSign != 0
}

Prevention

When it happens

Trigger: A certificate placed in the MSP's cacerts or intermediatecerts (loaded via setupCAs into rootCerts/intermediateCerts, sanitized, then finalized) has IsCA=false — i.e., an end-entity certificate used as a CA.

Common situations: Copying an admin/client certificate into cacerts by mistake; generating a CA without the CA basic constraint extension; a misconfigured fabric-ca or openssl CSR where basicConstraints CA:true was omitted; TestMalformedCertsChainSetup exercising this path in tests.

Understand the failure class

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/447bba4a9229620a. Report an issue: GitHub.