{"record":{"id":"8148d045cae84221","repo":"nats-io/nats-server","slug":"invalid-chain-link","errorCode":null,"errorMessage":"invalid chain link","messagePattern":"invalid chain link","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/certidp/ocsp_responder.go","lineNumber":31,"sourceCode":"\npackage certidp\n\nimport (\n\t\"encoding/base64\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\"time\"\n\n\t\"golang.org/x/crypto/ocsp\"\n)\n\nfunc FetchOCSPResponse(link *ChainLink, opts *OCSPPeerConfig, log *Log) ([]byte, error) {\n\tif link == nil || link.Leaf == nil || link.Issuer == nil || opts == nil || log == nil {\n\t\treturn nil, errors.New(ErrInvalidChainlink)\n\t}\n\n\ttimeout := time.Duration(opts.Timeout * float64(time.Second))\n\tif timeout <= 0*time.Second {\n\t\ttimeout = DefaultOCSPResponderTimeout\n\t}\n\n\tgetRequestBytes := func(u string, hc *http.Client) ([]byte, error) {\n\t\tresp, err := hc.Get(u)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdefer resp.Body.Close()\n\t\tif resp.StatusCode != http.StatusOK {\n\t\t\treturn nil, fmt.Errorf(ErrBadResponderHTTPStatus, resp.StatusCode)\n\t\t}\n\t\treturn io.ReadAll(resp.Body)\n\t}","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/certidp/ocsp_responder.go#L13-L49","documentation":"FetchOCSPResponse returns this error (ErrInvalidChainlink) when given a chain link it cannot use for an OCSP fetch: a nil link, a link missing the Leaf or Issuer certificate, or nil opts/log parameters. Without both certificates in the link, an OCSP request (which must name the issuer) cannot be constructed.","triggerScenarios":"Calling FetchOCSPChain/certOCSPGood path with a ChainLink whose Leaf or Issuer fields are nil, or passing nil for link, opts, or log.","commonSituations":"Incomplete certificate chains presented by peers (missing intermediate), chain assembly bugs in TLS config, or OCSP checking enabled without proper responder configuration.","solutions":["Ensure the served certificate chain includes the intermediate (issuer) certificate so ChainLink.Issuer is populated","Fix the code building ChainLink so Leaf and Issuer are always set before fetching OCSP","Provide a valid OCSPPeerConfig and Logger, or disable OCSP stapling if not configured","Validate the peer's chain completeness before enabling CertIDP/OCSP checks"],"exampleFix":"// before\nlink := &ChainLink{Leaf: cert} // Issuer missing\nresp, _ := certidp.FetchOCSPResponse(link, opts, log)\n// after\nif cert.Chain != nil && len(cert.Chain) > 1 {\n    link := &ChainLink{Leaf: cert, Issuer: cert.Chain[1]}\n    resp, err := certidp.FetchOCSPResponse(link, opts, log)\n}","handlingStrategy":"validation","validationCode":"func canFetchOCSP(link *certidp.ChainLink, opts *certidp.OCSPPeerConfig) bool {\n    return link != nil && link.Leaf != nil && link.Issuer != nil && opts != nil\n}\nif !canFetchOCSP(link, opts) {\n    return fmt.Errorf(\"incomplete chain link: leaf/issuer required for OCSP\")\n}","typeGuard":"func validChainLink(l *certidp.ChainLink) bool {\n    return l != nil && l.Leaf != nil && l.Issuer != nil\n}","tryCatchPattern":"resp, err := certidp.FetchOCSPResponse(link, opts, log)\nif err != nil {\n    log.Warnf(\"OCSP fetch failed for %s: %v\", link.Leaf.Subject, err)\n    return false, err\n}","preventionTips":["Always serve/inspect the full chain including intermediates","Check Leaf and Issuer are non-nil before OCSP calls","Configure OCSPPeerConfig completely before enabling CertIDP"],"tags":["tls","ocsp","certificates","pkix","validation"],"backgroundTag":"invalid-certificate-chain","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}