Skip to content

fix: cert_status reports valid certs as EXPIRED when the chain can't be verified (closes #881)#1270

Open
JamBalaya56562 wants to merge 1 commit into
nginx-proxy:mainfrom
JamBalaya56562:fix/cert-status-false-expired
Open

fix: cert_status reports valid certs as EXPIRED when the chain can't be verified (closes #881)#1270
JamBalaya56562 wants to merge 1 commit into
nginx-proxy:mainfrom
JamBalaya56562:fix/cert-status-false-expired

Conversation

@JamBalaya56562

Copy link
Copy Markdown
Contributor

What

/app/cert_status no longer reports a still-valid certificate as EXPIRED just because its chain fails to verify.

Why

cert_status ran openssl verify -untrusted chain.pem fullchain.pem and labelled any failure as EXPIRED:

if verify=$(openssl verify ...); then
    echo "$verify"
else
    echo "${cert}: EXPIRED"   # ← every verify failure becomes "EXPIRED"
fi

But openssl verify also fails when a trust anchor in the chain has expired (the classic DST Root CA X3 expiry, Sep 2021) even though the leaf certificate itself is still valid. Users with valid, freshly-renewed certificates saw them reported as EXPIRED (#881), which is misleading (the certificate/renewal logic itself was fine).

How

Determine expiry from the leaf certificate's own notAfter using openssl x509 -checkend 0, rather than treating a chain-verification failure as expiry:

  • If openssl verify succeeds → OK (unchanged).
  • If it fails but the leaf is still valid → OK (chain verification failed) (was wrongly EXPIRED).
  • If the leaf is actually expired → EXPIRED (unchanged).

Added test/tests/cert_status/ — a deterministic test (no ACME server needed) that generates a valid self-signed cert (chain unverifiable) and an expired one, and asserts the valid one is not reported EXPIRED while the expired one is.

Testing

  • New cert_status test passes locally and is registered in test/config.sh + the CI matrix.
  • Manually confirmed the output:
    • valid leaf, unverifiable chain → ... OK (chain verification failed) / Certificate is valid until …
    • expired leaf → ... EXPIRED / Certificate was valid until …
  • shellcheck clean on the modified script and the new test.

Closes #881

🤖 Generated with Claude Code

@buchdag buchdag force-pushed the fix/cert-status-false-expired branch from 91e2fb4 to cd70f17 Compare June 19, 2026 12:35
@buchdag buchdag added the type/fix PR for a bug fix label Jun 19, 2026

@buchdag buchdag left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we want to add a test here, the app/cert_status util is kinda provided as-is and is not part of the core features of acme-companion. WDYT ?

…ilure

cert_status ran `openssl verify` and labelled ANY failure as EXPIRED. But verify
also fails when a trust anchor in the chain is expired (e.g. DST Root CA X3) while
the leaf certificate is still valid, so valid certs were wrongly shown as EXPIRED
(nginx-proxy#881).

Determine expiry from the leaf's own notAfter (openssl x509 -checkend): if the leaf
is still valid but the chain can't be verified, report "OK (chain verification
failed)" instead of EXPIRED. Genuinely expired certs are still reported EXPIRED.

Closes nginx-proxy#881

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@JamBalaya56562 JamBalaya56562 force-pushed the fix/cert-status-false-expired branch from cd70f17 to 64ebb5c Compare June 19, 2026 12:59
@JamBalaya56562

Copy link
Copy Markdown
Contributor Author

Good point — dropped the test and kept just the app/cert_status fix, since the util is provided as-is. Also rebased onto main to clear the conflict. 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/fix PR for a bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fullchain.pem expired / force renewal doesn't renew

2 participants