QTS SSL Certificate 2.2.73: letsencrypt_agent_cli binary appends expired DST Root CA X3 to certificate chain, breaking strict TLS clients (Alexa, AWS Lambda)

Environment

  • QTS SSL Certificate: v2.2.73 (build 20260310, updated 2026-07-09 — latest)

  • Domain: custom DDNS (*.myqnapcloud.com)

  • Nginx fronting Home Assistant

Bug

After every Let’s Encrypt renewal, QcloudSSLCertificate’s letsencrypt_agent_cli binary appends the expired DST Root CA X3 certificate (expired September 30, 2021) to /etc/stunnel/uca.pem. This breaks TLS verification for any strict client like Alexa Smart Home, AWS Lambda, curl without -k, etc. even though the leaf cert and chain are perfectly valid.

Root cause

The acme-tiny step correctly fetches only the YR1 intermediate:

cert/chain → YR1 only (that’s good)

But letsencrypt_agent_cli then writes intermediate.pem (copied to uca.pem) as:

cert/intermediate.pem → YR1 + DST Root CA X3 (expired 2021) (that’s bad)

The DST cert is being hardcoded into the binary’s certificate assembly step. cert/chain (the raw acme-tiny output) is clean — the corruption happens inside the compiled binary.

This happens probably because LetsEncrypt changed the CAs hierarchy on May 27 2026 (source1)

Verification

# cert/chain — clean

openssl x509 -noout -subject -dates -in /mnt/ext/opt/QcloudSSLCertificate/cert/chain

# subject=C=US, O=Let’s Encrypt, CN=YR1 | notAfter=Sep 2 23:59:59 2028 GMT (good)

# cert/intermediate.pem — broken

awk ‘…’ /mnt/ext/opt/QcloudSSLCertificate/cert/intermediate.pem | openssl x509 -noout -subject -dates

# Cert 1: YR1 notAfter=Sep 2 2028 (good)

# Cert 2: DST Root CA X3 notAfter=Sep 30 14:01:15 2021 (bad)

Impact

Browsers ignore the extra cert and verify fine. But any client doing strict chain validation (Alexa Smart Home skill, AWS Lambda, standard curl) gets SSL: unable to get local issuer certificate and fails.

Workaround (until fixed)

A daily cron script that rebuilds nginx.pem from the clean files, stripping expired certs and appending the cross-signed ISRG Root YR:

0 4 * * * /share/CACHEDEV1_DATA/build_nginx_pem.sh

Fix needed

Remove the DST Root CA X3 hardcode from letsencrypt_agent_cli. The binary should use only the certs in cert/chain when building intermediate.pem/uca.pem.

Other OSS solution fix: