{"record":{"id":"612e6f63253b02cd","repo":"redis/redis-py","slug":"failed-to-fetch-ocsp-certificate","errorCode":null,"errorMessage":"failed to fetch ocsp certificate","messagePattern":"failed to fetch ocsp certificate","errorType":"exception","errorClass":"ConnectionError","httpStatus":null,"severity":"error","filePath":"redis/ocsp.py","lineNumber":287,"sourceCode":"    def check_certificate(self, server, cert, issuer_url):\n        \"\"\"Checks the validity of an ocsp server for an issuer\"\"\"\n\n        r = requests.get(issuer_url)\n        if not r.ok:\n            raise ConnectionError(\"failed to fetch issuer certificate\")\n        der = r.content\n        issuer_cert = self._bin2ascii(der)\n\n        ocsp_url = self.build_certificate_url(server, cert, issuer_cert)\n\n        # HTTP 1.1 mandates the addition of the Host header in ocsp responses\n        header = {\n            \"Host\": urlparse(ocsp_url).netloc,\n            \"Content-Type\": \"application/ocsp-request\",\n        }\n        r = requests.get(ocsp_url, headers=header)\n        if not r.ok:\n            raise ConnectionError(\"failed to fetch ocsp certificate\")\n        return _check_certificate(issuer_cert, r.content, True)\n\n    def is_valid(self):\n        \"\"\"Returns the validity of the certificate wrapping our socket.\n        This first retrieves for validate the certificate, issuer_url,\n        and ocsp_server for certificate validate. Then retrieves the\n        issuer certificate from the issuer_url, and finally checks\n        the validity of OCSP revocation status.\n        \"\"\"\n\n        # validate the certificate\n        try:\n            cert, issuer_url, ocsp_server = self.components_from_socket()\n            if issuer_url is None:\n                raise ConnectionError(\"no issuers found in certificate chain\")\n            return self.check_certificate(ocsp_server, cert, issuer_url)\n        except AuthorizationError:\n            cert, issuer_url, ocsp_server = self.components_from_direct_connection()","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/ocsp.py#L269-L305","documentation":"Raised as a ConnectionError by OCSPVerifier.check_certificate (redis/ocsp.py:287) when requests.get(ocsp_url).ok is False — the HTTP GET to the OCSP responder returned a non-2xx status. This happens after the issuer cert was fetched successfully and the OCSP request URL was built; the responder itself rejected or errored on the request. Note the GET method used here is technically non-standard (RFC 6960 defines POST for full requests), which some responders reject.","triggerScenarios":"OCSPVerifier.check_certificate builds the OCSP URL via build_certificate_url (base64-encodes the DER request and appends it to the responder URL), then requests.get(ocsp_url) returns non-OK. Responder returns 4xx/5xx, the responder rejects GET-based OCSP (expects POST), or the network path fails.","commonSituations":"OCSP responder that only accepts POST (RFC 6960 sec A.1.1) and returns 405/400 for the GET form redis-py uses; responder down or rate-limiting (429); responder requires authentication; firewall blocks the responder URL; URL malformed by base64 padding/encoding issues.","solutions":["Confirm the OCSP responder accepts the GET (base64-encoded) OCSP request form; if it requires POST, this path cannot work and you may need a different verification approach.","Verify the responder URL and network reachability (curl the responder base URL).","Check for rate limiting (429) or maintenance status from the responder.","If the responder requires signed requests or specific headers, ensure they are configured (note the current implementation sends Host + Content-Type only)."],"exampleFix":"# before - responder returns non-2xx for the OCSP GET\nverifier.is_valid()  # ConnectionError: failed to fetch ocsp certificate\n\n# after - verify responder supports GET-based OCSP and is reachable\n# curl -sSI 'http://ocsp.example.com/<base64-request>'  -> expect 200 application/ocsp-response\n# if responder is POST-only, use an OCSP path that issues POST (e.g. ocsp_staple_verifier with server-side stapling)","handlingStrategy":"try-catch","validationCode":"import requests\n\ndef ocsp_responder_accepts_get(ocsp_url, timeout=5):\n    try:\n        r = requests.get(ocsp_url, timeout=timeout)\n        return r.ok\n    except requests.RequestException:\n        return False","typeGuard":null,"tryCatchPattern":"from redis.exceptions import ConnectionError as RedisConnectionError\n\ntry:\n    verifier.is_valid()\nexcept RedisConnectionError as e:\n    if 'failed to fetch ocsp certificate' in str(e):\n        logging.warning('OCSP responder GET failed - responder may be POST-only or unreachable: %s', e)\n    raise","preventionTips":["Confirm the OCSP responder accepts the GET (base64-encoded) OCSP request form redis-py uses.","Verify the responder URL is reachable and not rate-limiting (curl the responder base URL).","If the responder is POST-only, use OCSP stapling (server-side) so the client verifies a server-fetched response.","Watch for responder maintenance windows and 429 rate limiting."],"tags":["ocsp","ssl","tls","security","network","responder","http","certificate","connection"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}