Skip to content

tls: include every CA in the trusted bundle when generating TLS session IDs - #47405

Merged
ggreenway merged 1 commit into
envoyproxy:mainfrom
abhinav-phi:tls-session-id-all-ca-certs
Sep 15, 2026
Merged

ggreenway merged 1 commit into
envoyproxy:mainfrom
abhinav-phi:tls-session-id-all-ca-certs

Conversation

@abhinav-phi

Copy link
Copy Markdown
Contributor

Commit Message: tls: include every CA in the trusted bundle when generating TLS session IDs

DefaultCertValidator::updateDigestForSessionId() hashed only ca_cert_, which is assigned once to the first X509 encountered in the trusted CA PEM bundle. A change to any CA after the first one (e.g. a rotation or removal through an xDS update) therefore did not invalidate previously issued session IDs, and a resumed session could be accepted without validation against the current trust bundle.

The digest now includes the SHA-256 of every certificate in the parsed bundle (shared_ca_certs_->certs), mirroring what the SPIFFE validator already does for its CA list.

Compatibility: a trusted bundle with a single certificate produces byte-identical digest input to the previous behavior. Multi-CA bundles will reissue session IDs once after the upgrade (one-time increase in full handshakes), which is the intended security fix, so no runtime guard is added; the SPIFFE validator ships the same behavior unguarded.

Fixes #47238


  • Commit Message: commit message matches the PR title and describes the fix.
  • Risk Level: low — the change affects only the digest that keys TLS session resumption; certificate validation itself is unchanged.
  • Testing: added DefaultCertValidatorTest.SessionIdDigestCoversAllCaCertificates in test/common/tls/cert_validator/default_validator_test.cc, which asserts that (a) adding a CA after the first one changes the digest and (b) rotating only a non-first CA changes the digest — both regressions of the old behavior. Existing TLS unit tests cover the single-CA byte-compatibility path.
  • Docs: release note fragment added under changelogs/current/bug_fixes/tls__session-id-digest-covers-all-ca-certs.rst.

…on IDs

DefaultCertValidator::updateDigestForSessionId() hashed only ca_cert_,
which is assigned to the first X509 encountered in the trusted CA PEM
bundle. Consequently a change to any CA after the first one, e.g. a
rotation or removal via an xDS update, did not invalidate previously
issued session IDs, and a resumed session could be accepted without
being validated against the current trust bundle.

Hash the digest of every certificate in the shared parsed bundle
(shared_ca_certs_->certs) instead, mirroring what the SPIFFE validator
already does for its CA list. A bundle containing a single certificate
produces byte-identical digest input to the previous behavior;
multi-certificate bundles will reissue session IDs once after the
upgrade, causing a one-time increase in full handshakes.

Signed-off-by: abhinav-phi <alpha9coder@gmail.com>
@abhinav-phi
abhinav-phi deployed to external-contributors September 13, 2026 11:03 — with GitHub Actions Active
@repokitteh-read-only

Copy link
Copy Markdown

Hi @abhinav-phi, welcome and thank you for your contribution.

We will try to review your Pull Request as quickly as possible.

In the meantime, please take a look at the contribution guidelines if you have not done so already.

🐱

Caused by: #47405 was opened by abhinav-phi.

see: more, trace.

@abhinav-phi

Copy link
Copy Markdown
Contributor Author

Friendly ping: the CI workflow for this first-time-contributor PR is still waiting for maintainer approval (the authorize check has been pending since #47405 was opened). Could someone please approve the workflow run? Happy to address any feedback — thanks! This fixes #47238.

// the client connection. This ensures that the client is always validated against
// the correct settings, even if session resumption across different listeners
// is enabled.
if (ca_cert_ != nullptr) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this field still necessary?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It is still needed, but only for first-CA reporting. ca_cert_ is assigned at default_validator.cc:224 and read by getCaCertInformation(), initializeCertExpirationStats() and daysUntilFirstCertExpires(). Now that the digest no longer uses it, it is only a duplicate reference to shared_ca_certs_->certs[0] (CaCertCache::getOrCreate() never returns an empty bundle), so those three can read the first entry of the shared bundle directly and the member can be dropped.

Happy to push that as an extra commit on this PR, but it is a pure no-behavior-change refactor of the cert-info/expiration reporting path, so say the word if you would rather keep this PR limited to the digest fix and see it as a separate change.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not needed. BTW since this sounds like Claude, please disclose the AI usage.

@ggreenway ggreenway 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.

LGTM

@ggreenway
ggreenway enabled auto-merge (squash) September 15, 2026 18:36
@ggreenway
ggreenway merged commit 46dbbf9 into envoyproxy:main Sep 15, 2026
24 of 25 checks passed
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.

DefaultCertValidator includes only the first CA cert in the digest for TLS session ID generation

3 participants