grpc/grpc-go · error

spiffe: verify function could not parse input certificate: %

Error message

spiffe: verify function could not parse input certificate: %v

What it means

During SPIFFE-based mTLS verification (bundle.go:160-166), the server's raw certificate bytes are parsed with x509.ParseCertificate. If a raw cert blob cannot be parsed as an X.509 certificate (corrupt, malformed, or non-ASN.1 data), this error fires inside the VerifyPeerCertificate callback. The underlying parse error is included.

Source

Thrown at internal/xds/bootstrap/tlscreds/bundle.go:166

func (c *reloadingCreds) Clone() credentials.TransportCredentials {
	return &reloadingCreds{provider: c.provider}
}

func (c *reloadingCreds) OverrideServerName(string) error {
	return errors.New("overriding server name is not supported by xDS client TLS credentials")
}

func (c *reloadingCreds) ServerHandshake(net.Conn) (net.Conn, credentials.AuthInfo, error) {
	return nil, nil, errors.New("server handshake is not supported by xDS client TLS credentials")
}

func buildSPIFFEVerifyFunc(spiffeBundleMap map[string]*spiffebundle.Bundle) func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
	return func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
		rawCertList := make([]*x509.Certificate, len(rawCerts))
		for i, asn1Data := range rawCerts {
			cert, err := x509.ParseCertificate(asn1Data)
			if err != nil {
				return fmt.Errorf("spiffe: verify function could not parse input certificate: %v", err)
			}
			rawCertList[i] = cert
		}
		if len(rawCertList) == 0 {
			return fmt.Errorf("spiffe: verify function has no valid input certificates")
		}
		leafCert := rawCertList[0]
		roots, err := spiffe.GetRootsFromSPIFFEBundleMap(spiffeBundleMap, leafCert)
		if err != nil {
			return err
		}

		opts := x509.VerifyOptions{
			Roots:         roots,
			CurrentTime:   time.Now(),
			Intermediates: x509.NewCertPool(),
		}

View on GitHub (pinned to 03255a9237)

Solutions

  1. Verify the xDS management server presents a valid X.509 certificate chain using openssl s_client against its endpoint.
  2. If a TLS-terminating proxy is in the path, ensure it forwards the real server certificate rather than a placeholder.
  3. Confirm SPIFFE verification is actually intended for this deployment; if not, disable the SPIFFE trust bundle map.
  4. Inspect the underlying parse error to determine whether the bytes are truncated or a non-cert payload.

Example fix

# diagnose the presented certificate:
#   openssl s_client -connect xds-server:443 -showcerts
# if corrupt, fix the server cert; if SPIFFE is not intended,
# remove spiffe_trust_bundle_map_file from the bootstrap
Defensive patterns

Strategy: try-catch

Validate before calling

// Before connecting, verify the server presents parseable certs.
func probeServerCert(addr string) error {
    conf := &tls.Config{InsecureSkipVerify: true}
    conn, err := tls.Dial("tcp", addr, conf)
    if err != nil { return err }
    defer conn.Close()
    if len(conn.ConnectionState().PeerCertificates) == 0 {
        return errors.New("server presented no certificates")
    }
    return nil
}

Try / catch

// The SPIFFE verify error surfaces during ClientHandshake; surface it.
if err := creds.ClientHandshake(ctx, authority, conn); err != nil {
    if strings.Contains(err.Error(), "spiffe: verify function could not parse") {
        // server cert is corrupt/malformed; flag to ops
    }
    return err
}

Prevention

When it happens

Trigger: A server presents a certificate whose DER encoding is malformed, or the raw cert slice contains data that is not a certificate at all. This occurs at TLS handshake time when InsecureSkipVerify is set and the custom SPIFFE verifier is invoked.

Common situations: The xDS management server is misconfigured and presenting a corrupt or placeholder certificate; a TLS-terminating proxy in the path alters the certificate chain; an intermediate box injects unexpected bytes; the SPIFFE trust bundle map is enabled (GRPC_XDS_SPIFFE_ENABLED) and the server is not actually SPIFFE-aware.

Understand the failure class

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/7ea05dfaca2e98f6. Report an issue: GitHub.