{"record":{"id":"6d699e24b6676e4f","repo":"redis/redis-py","slug":"no-matching-issuer-cert-found-in-certificate-chain","errorCode":null,"errorMessage":"no matching issuer cert found in certificate chain","messagePattern":"no matching issuer cert found in certificate chain","errorType":"exception","errorClass":"ConnectionError","httpStatus":null,"severity":"error","filePath":"redis/ocsp.py","lineNumber":160,"sourceCode":"def ocsp_staple_verifier(con, ocsp_bytes, expected=None):\n    \"\"\"An implementation of a function for set_ocsp_client_callback in PyOpenSSL.\n\n    This function validates that the provide ocsp_bytes response is valid,\n    and matches the expected, stapled responses.\n    \"\"\"\n    if ocsp_bytes in [b\"\", None]:\n        raise ConnectionError(\"no ocsp response present\")\n\n    issuer_cert = None\n    peer_cert = con.get_peer_certificate().to_cryptography()\n    for c in con.get_peer_cert_chain():\n        cert = c.to_cryptography()\n        if cert.subject == peer_cert.issuer:\n            issuer_cert = cert\n            break\n\n    if issuer_cert is None:\n        raise ConnectionError(\"no matching issuer cert found in certificate chain\")\n\n    if expected is not None:\n        e = x509.load_pem_x509_certificate(expected)\n        if peer_cert != e:\n            raise ConnectionError(\"received and expected certificates do not match\")\n\n    return _check_certificate(issuer_cert, ocsp_bytes)\n\n\nclass OCSPVerifier:\n    \"\"\"A class to verify ssl sockets for RFC6960/RFC6961. This can be used\n    when using direct validation of OCSP responses and certificate revocations.\n\n    @see https://datatracker.ietf.org/doc/html/rfc6960\n    @see https://datatracker.ietf.org/doc/html/rfc6961\n    \"\"\"\n\n    def __init__(self, sock, host, port, ca_certs=None):","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/ocsp.py#L142-L178","documentation":"Raised as a ConnectionError by ocsp_staple_verifier (redis/ocsp.py:160) when iterating the peer certificate chain yields no certificate whose subject equals peer_cert.issuer — i.e. the chain does not contain the immediate issuer of the peer certificate. _verify_response needs the issuer's public key to validate the OCSP response signature, so without it verification cannot proceed.","triggerScenarios":"ocsp_staple_verifier runs on a TLS connection where the server sent an incomplete chain (missing the intermediate/issuer cert), or the chain is ordered such that no entry's subject matches peer_cert.issuer. The loop over con.get_peer_cert_chain() finds no match and issuer_cert stays None.","commonSituations":"Server misconfigured to send only the leaf cert (no intermediate); intermediate not installed on the server TLS config; chain sent in an order/format PyOpenSSL doesn't expose fully; cross-signed cert where the expected issuer differs from what was sent; client-side trust store doesn't change this — the chain must be server-sent.","solutions":["Configure the server to send the full certificate chain including the intermediate/issuer certificate (most TLS stacks: concatenate leaf + intermediate in the cert file).","Verify the chain presented using openssl s_client to confirm the issuer cert appears.","If using stunnel/Redis TLS, ensure ssl_cert includes the full chain, not just the leaf.","Confirm peer_cert.issuer actually corresponds to a cert in the sent chain (cross-signing can cause a mismatch)."],"exampleFix":"# before - server sends leaf only\n# server: ssl_cert = /etc/ssl/leaf.crt\nocsp_staple_verifier(con, ocsp_bytes)  # ConnectionError: no matching issuer cert found in certificate chain\n\n# after - server sends the full chain\n# server: ssl_cert = /etc/ssl/fullchain.crt   (leaf + intermediate concatenated)\n# verify: openssl s_client -connect host:port -showcerts  # shows leaf + issuer","handlingStrategy":"validation","validationCode":"def chain_contains_issuer(con, peer_cert):\n    for c in con.get_peer_cert_chain():\n        cert = c.to_cryptography()\n        if cert.subject == peer_cert.issuer:\n            return True\n    return False","typeGuard":null,"tryCatchPattern":"from redis.exceptions import ConnectionError as RedisConnectionError\n\ntry:\n    ocsp_staple_verifier(con, ocsp_bytes, expected)\nexcept RedisConnectionError as e:\n    if 'no matching issuer cert found' in str(e):\n        logging.warning('Incomplete chain - server must send the issuer/intermediate cert')\n    raise","preventionTips":["Configure the server to present the full chain (leaf + intermediate) in its TLS cert file.","Verify with `openssl s_client -showcerts` that the issuer cert is sent.","Keep intermediate certs installed alongside the leaf on the server.","Watch for cross-signing mismatches where peer_cert.issuer differs from the sent chain."],"tags":["ocsp","ssl","tls","security","certificate-chain","certificate","connection"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}