From 3fd30ff50d372beff45f9df19600891cf70ea41f Mon Sep 17 00:00:00 2001 From: sysangels | Michal Koeckeis-Fresel Date: Sun, 8 Mar 2026 17:43:42 +0100 Subject: [PATCH] UI certificate parser fails with MalformedFraming on fullchain.pem get only the first certificate in chain #3255 --- src/common/core/letsencrypt/ui/actions.py | 10 +++++++++- .../core/letsencrypt/ui/blueprints/letsencrypt.py | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/common/core/letsencrypt/ui/actions.py b/src/common/core/letsencrypt/ui/actions.py index d5b7bce585..06a31a4de0 100644 --- a/src/common/core/letsencrypt/ui/actions.py +++ b/src/common/core/letsencrypt/ui/actions.py @@ -66,7 +66,15 @@ def retrieve_certificates_info(folder_paths: Tuple[Path, Path]) -> dict: # * Parsing the certificate try: - cert = x509.load_pem_x509_certificate(cert_file.read_bytes(), default_backend()) + pem_data = cert_file.read_bytes() + # fullchain.pem contains the leaf cert followed by one or more intermediates. + # load_pem_x509_certificate only accepts a single block; strip everything + # after the first END marker so newer cryptography versions don't raise MalformedFraming. + _end_marker = b"-----END CERTIFICATE-----" + _first_end = pem_data.find(_end_marker) + if _first_end != -1: + pem_data = pem_data[: _first_end + len(_end_marker)] + cert = x509.load_pem_x509_certificate(pem_data, default_backend()) # ? Getting the subject subject = cert.subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME) diff --git a/src/common/core/letsencrypt/ui/blueprints/letsencrypt.py b/src/common/core/letsencrypt/ui/blueprints/letsencrypt.py index 1048e991f1..77052f52d8 100644 --- a/src/common/core/letsencrypt/ui/blueprints/letsencrypt.py +++ b/src/common/core/letsencrypt/ui/blueprints/letsencrypt.py @@ -123,7 +123,15 @@ def retrieve_certificates(): "key_type": "Unknown", } try: - cert = x509.load_pem_x509_certificate(cert_file.read_bytes(), default_backend()) + pem_data = cert_file.read_bytes() + # fullchain.pem contains the leaf cert followed by one or more intermediates. + # load_pem_x509_certificate only accepts a single block; strip everything + # after the first END marker so newer cryptography versions don't raise MalformedFraming. + _end_marker = b"-----END CERTIFICATE-----" + _first_end = pem_data.find(_end_marker) + if _first_end != -1: + pem_data = pem_data[: _first_end + len(_end_marker)] + cert = x509.load_pem_x509_certificate(pem_data, default_backend()) subject = cert.subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME) if subject: cert_info["common_name"] = subject[0].value