nats-io/nats-server · error

failed to parse OCSP response: %w

Error message

failed to parse OCSP response: %w

What it means

After extracting the leaf and issuer from the verified chain, GetOCSPStatus parses the stapled OCSPResponse via ocsp.ParseResponseForCert. If the response bytes are missing, malformed, or don't correspond to the certificate, the underlying parse error is wrapped with this message.

Source

Thrown at internal/ocsp/ocsp.go:243

		t.Fatalf("failed to decode PEM %s", pemPath)
	}
	return block
}

func GetOCSPStatus(s tls.ConnectionState) (*ocsp.Response, error) {
	if len(s.VerifiedChains) == 0 {
		return nil, fmt.Errorf("missing TLS verified chains")
	}
	chain := s.VerifiedChains[0]

	if got, want := len(chain), 2; got < want {
		return nil, fmt.Errorf("incomplete cert chain, got %d, want at least %d", got, want)
	}
	leaf, issuer := chain[0], chain[1]

	resp, err := ocsp.ParseResponseForCert(s.OCSPResponse, leaf, issuer)
	if err != nil {
		return nil, fmt.Errorf("failed to parse OCSP response: %w", err)
	}
	if err := resp.CheckSignatureFrom(issuer); err != nil {
		return resp, err
	}
	return resp, nil
}

func SetOCSPStatus(t *testing.T, ocspURL, certPEM string, status int) {
	t.Helper()

	cert := parseCertPEM(t, certPEM)

	hc := &http.Client{Timeout: 10 * time.Second}
	resp, err := hc.Post(
		fmt.Sprintf("%s/statuses/%s", ocspURL, cert.SerialNumber),
		"",
		strings.NewReader(fmt.Sprint(status)),
	)

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Verify OCSPResponse is non-empty before calling GetOCSPStatus and skip OCSP checks if absent
  2. Confirm the OCSP responder serves a response for the leaf's serial signed by the expected issuer
  3. Re-staple: have the client fetch a fresh OCSP response from the CA's responder

Example fix

// before
resp, err := GetOCSPStatus(cs)
// after
if len(cs.OCSPResponse) == 0 {
    return nil, errors.New("no stapled OCSP response")
}
resp, err := GetOCSPStatus(cs)
Defensive patterns

Strategy: validation

Validate before calling

cs := conn.ConnectionState()
if len(cs.OCSPResponse) == 0 {
    return errors.New("no stapled OCSP response to check")
}

Try / catch

resp, err := GetOCSPStatus(cs)
if err != nil {
    var inner error
    if strings.HasPrefix(err.Error(), "failed to parse OCSP response:") {
        errors.As(err, &inner) // inspect underlying ocsp/asn1 error
        return nil, fmt.Errorf("stapled OCSP unusable: %w", inner)
    }
    return err
}

Prevention

When it happens

Trigger: Calling GetOCSPStatus on a connection where tls.ConnectionState.OCSPResponse is empty or not a valid DER-encoded OCSP response for the leaf/issuer pair.

Common situations: Client did not staple an OCSP response (empty OCSPResponse); stapled response is stale, re-signed, or for a different serial; intermediary proxy stripped the stapled response.

Understand the failure class

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/992dfc19848a8dae. Report an issue: GitHub.