Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(gatewayapi): reject entire cert chain when leaf is expired#9248

Open
AruneshDwivedi wants to merge 4 commits into
envoyproxy:mainfrom
AruneshDwivedi:fix/expired-cert-chain-stall
Open

fix(gatewayapi): reject entire cert chain when leaf is expired#9248
AruneshDwivedi wants to merge 4 commits into
envoyproxy:mainfrom
AruneshDwivedi:fix/expired-cert-chain-stall

Conversation

@AruneshDwivedi

@AruneshDwivedi AruneshDwivedi commented Jun 18, 2026

Copy link
Copy Markdown

When a TLS secret contains a certificate chain where the leaf certificate is expired but the intermediate CA is still valid, filterValidCertificates was filtering out only the expired leaf. The remaining chain (intermediate CA only) was passed to Envoy, which then rejected it with KEY_VALUES_MISMATCH because the private key belongs to the leaf, not the CA.

This fix checks if the first PEM block (the leaf) is expired. If it is, the entire chain is rejected -- same as if all certs were expired.

Fixes #9225

When a TLS secret contains a certificate chain where the leaf certificate
is expired but the intermediate CA is still valid, filterValidCertificates
was filtering out only the expired leaf and keeping the intermediate.

This caused the intermediate CA to be passed to Envoy as the 'certificate',
which doesn't match the private key (the private key matches the leaf).
Envoy then rejects this with KEY_VALUES_MISMATCH, causing a configuration
stall where no envoy configurations get updated.

Fix: track whether the first PEM block (leaf certificate) was invalid, and
if so, reject the entire chain with InvalidCertificateRef. This ensures
that a partial chain is never passed to Envoy.

Also adds:
- TestFilterValidCertificates_ExpiredLeafWithValidChain: generates an
  expired leaf + valid intermediate programmatically and verifies the
  entire chain is rejected

Fixes envoyproxy#9225

Signed-off-by: Arunesh Dwivedi <[email protected]>
@AruneshDwivedi AruneshDwivedi requested a review from a team as a code owner June 18, 2026 10:55
@netlify

netlify Bot commented Jun 18, 2026

Copy link
Copy Markdown

Deploy Preview for cerulean-figolla-1f9435 ready!

Name Link
🔨 Latest commit f271491
🔍 Latest deploy log https://app.netlify.com/projects/cerulean-figolla-1f9435/deploys/6a4cb95b6525310008c1b26c
😎 Deploy Preview https://deploy-preview-9248--cerulean-figolla-1f9435.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2f9e4f9cf9

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread internal/gatewayapi/tls.go Outdated
Comment on lines +238 to +240
if blockIndex == 0 {
firstBlockInvalid = true
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Don't reject recoverable leading malformed blocks

When the first PEM block is malformed but a later block is a valid certificate, this branch now makes filterValidCertificates return InvalidCertificateRef with no data before reaching the existing partial-invalid path. The existing TestFilterValidCertificates/bundle-first-invalid fixture covers exactly that case (malformed-cert.pem + rsa-cert.pem) and expects the valid RSA cert to be kept, so this change both breaks the unit test and rejects previously recoverable Secrets; the expired-leaf stall only requires treating a parsed, time-invalid leaf as chain-fatal, not parse errors that can still be skipped.

Useful? React with 👍 / 👎.

…blocks

Malformed PEM blocks (parse errors) are now skipped instead of being
treated as chain-fatal. Only the first PEM block being expired or
not-yet-valid triggers InvalidCertificateRef. This allows recovery
of valid certs from bundles where the first block is malformed.

Signed-off-by: Arunesh Dwivedi <[email protected]>
A malformed first block (parse failure) should not invalidate the whole
chain — subsequent valid certs can still be used. Only treat as
fully-invalid when the leaf cert parses but fails validation
(expired/not-yet-valid).

Signed-off-by: Arunesh Dwivedi <[email protected]>
@AruneshDwivedi

Copy link
Copy Markdown
Author

Parse failures and validation failures are handled differently here. When x509.ParseCertificates fails on the first block, blockIndex is incremented before the continue, so the firstBlockInvalid check is never reached for parse errors. firstBlockInvalid only triggers when the first block parses successfully but fails time-validation (expired/not-yet-valid). A malformed leading PEM block would fall through and let later valid blocks be recovered, preserving the existing PartiallyInvalidCertificateRef behavior.

@AruneshDwivedi

Copy link
Copy Markdown
Author

The Codex review misunderstands the control flow.

When fails (malformed PEM block), is incremented before the at line 238. This means:

  • Parse error on block 0 → becomes 1 → loop continues → is never set
  • Parse error on block 1+ → is already > 0 → is never set

is only set when a cert parses successfully but fails time validation (). That's exactly the intended behavior: reject the entire chain only when the leaf cert (first block) is expired/not-yet-valid, because the private key matches the leaf.

The existing fixture () validates this — malformed first block is skipped, valid second block is accepted. The new test validates the opposite: expired leaf + valid chain → entire chain rejected.

The code is correct as written.

@arkodg arkodg requested review from cnvergence and kkk777-7 July 8, 2026 05:00
@arkodg arkodg added this to the v1.9.0-rc.1 Release milestone Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expired certificate combined with valid chain causes configuration stall

2 participants