{"record":{"id":"621315f399c07121","repo":"redis/redis-py","slug":"no-issuers-found-in-certificate-chain","errorCode":null,"errorMessage":"no issuers found in certificate chain","messagePattern":"no issuers found in certificate chain","errorType":"exception","errorClass":"ConnectionError","httpStatus":null,"severity":"error","filePath":"redis/ocsp.py","lineNumber":302,"sourceCode":"        }\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()\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","sourceCodeStart":284,"sourceCodeEnd":309,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/ocsp.py#L284-L309","documentation":"Raised by OCSPValidator.is_valid() (redis/ocsp.py:302) during client-side OCSP revocation checking. After reading the peer certificate off the already-wrapped TLS socket via components_from_socket(), the code extracts the CA Issuers URL from the certificate's Authority Information Access (AIA) extension; if no CA_ISSUERS entry exists (IndexError caught at ocsp.py:226-227 sets issuer=None), redis-py cannot download the issuer certificate required to build an OCSP request, so it aborts with ConnectionError. The server certificate must carry an AIA extension with a reachable CA Issuers URI for OCSP validation to proceed.","triggerScenarios":"Constructing a client with OCSP validation enabled (e.g. ssl=True plus an OCSPValidator / ssl_ocsp_context) against a Redis server whose TLS certificate has no AIA extension, an AIA extension without a CA_ISSUERS access method, or a CA_ISSUERS entry whose access_location is empty. Specifically, components_from_socket() returns (cert, None, ocsp_server) and the `if issuer_url is None` branch at ocsp.py:301 fires.","commonSituations":"Self-signed or internally-issued certificates that omit AIA; private CAs that do not publish an AIA URI; stunnel or a TLS-terminating proxy presenting a cert without OCSP/AIA info; test certificates generated with plain `openssl req -x509` and no AIA extension.","solutions":["Provision a server certificate whose AIA extension includes an http(s) CA Issuers URL pointing to the issuer's DER-encoded certificate.","Regenerate the cert with AIA, e.g. `openssl x509 -req ... -extfile <(printf 'authorityInfoAccess=CA Issuers;URI:https://ca.example.com/issuer.cer')`.","If OCSP revocation checking is not required for your deployment, drop the OCSPValidator / ssl_ocsp_context from the client config.","As a last resort set ssl_cert_reqs=ssl.CERT_NONE ONLY if you fully understand the security implications (NOT recommended for production)."],"exampleFix":"# before: cert has no AIA -> ConnectionError: no issuers found in certificate chain\nr = redis.Redis(host=..., ssl=True, ssl_ocsp_context=ocsp_ctx)\n\n# after (option A): server cert regenerated with AIA CA Issuers URI\n# (server-side change, no client edit needed)\n\n# after (option B): disable OCSP validation if not required\nr = redis.Redis(host=..., ssl=True, ssl_cert_reqs=\"required\")","handlingStrategy":"validation","validationCode":"from cryptography import x509\nfrom cryptography.x509.oid import ExtensionOID, AuthorityInformationAccessOID\n\ndef cert_has_issuer_url(pem_bytes: bytes) -> bool:\n    cert = x509.load_pem_x509_certificate(pem_bytes)\n    try:\n        aia = cert.extensions.get_extension_for_oid(\n            ExtensionOID.AUTHORITY_INFORMATION_ACCESS\n        ).value\n    except x509.ExtensionNotFound:\n        return False\n    return any(\n        ext.access_method == AuthorityInformationAccessOID.CA_ISSUERS\n        for ext in aia\n    )\n\n# run BEFORE enabling OCSP:\n# assert cert_has_issuer_url(server_pem), 'cert lacks AIA CA Issuers URL'","typeGuard":"from cryptography import x509\nfrom cryptography.x509.oid import ExtensionOID, AuthorityInformationAccessOID\n\ndef has_reachable_aia_issuer(cert) -> bool:\n    try:\n        aia = cert.extensions.get_extension_for_oid(\n            ExtensionOID.AUTHORITY_INFORMATION_ACCESS\n        ).value\n    except x509.ExtensionNotFound:\n        return False\n    return any(\n        e.access_method == AuthorityInformationAccessOID.CA_ISSUERS\n        and str(e.access_location.value).startswith(('http://', 'https://'))\n        for e in aia\n    )","tryCatchPattern":"import redis\ntry:\n    client = redis.Redis(host=..., ssl=True, ssl_ocsp_context=ctx)\n    client.ping()\nexcept redis.ConnectionError as e:\n    if 'no issuers found in certificate chain' in str(e):\n        # server cert lacks AIA CA Issuers URL; disable OCSP or reissue cert\n        ...","preventionTips":["Generate all TLS certs with an AIA extension pointing to a reachable CA Issuers URI.","Validate certs in CI with a script that asserts has_reachable_aia_issuer() before deploying.","Keep OCSP validation off for dev/test unless your test CA publishes AIA and OCSP endpoints."],"tags":["tls","ocsp","ssl","certificates","security"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}