Path building re-parses every intermediate on each budgeted call (unbudgeted CPU cost)

Open
#540 0 comments 0 reactions 0 assignees View on GitHub

@batmnnn is already working on this.

Since Oct 23, 2026.

  • #1 by @batmnnn — open
  • #548 by @batmnnn — open

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
72/100
Issue type
Refactor
Clarity
Clearly specified
Activity status
Active
Tech stack
rust
Domain
cryptography

Research direction

Start at src/verify_cert.rs, in build_chain_inner/PathBuilder where the issue links lines 149-150: each recursive step calls Cert::from_der over all intermediate_certs before the issuer comparison. Hoist that parsing into a Vec<Cert> built once at the start of build_chain (skipping or recording parse failures), keeping Budget semantics unchanged. Read the Budget definition and the test_too_many_path_calls regression test first, then run cargo test to confirm budget and path-building tests still pass; done means intermediates are parsed once and the per-recursion step is only a name comparison.

Written by the indexing model from the issue text.

Description

While reviewing rustls-webpki 0.103.15 we noticed that path building re-parses every peer-supplied intermediate on each budgeted path-building call, and that this parsing is not itself counted against the budget.

Where. In build_chain_inner (ChainOptions in 0.103.15, PathBuilder on main), every recursive step iterates over all of intermediate_certs and calls Cert::from_der on each one before the issuer comparison (0.103.15 src/verify_cert.rs:108; on current main at https://github.com/rustls/webpki/blob/3d0adc46704c1d985a9fefe2034650488d96d49e/src/verify_cert.rs#L149-L150). The Budget (the RUSTSEC-2023-0053 fix) limits build-chain calls and signature checks, but the per-call parse of each intermediate is outside it.

Cost. This is bounded: at most the 200,000-call budget times the bytes of intermediates, and rustls caps the Certificate message at 64 KiB. In practice, a filler-padded chain that fits in a 64 KiB handshake message costs about 0.5-1 s of CPU per handshake on our hardware (worst measured 758 ms). Plain degenerate chains (the test_too_many_path_calls shape) stop within about 66 ms. So a malicious TLS server can make a client spend up to roughly a second of CPU per connection attempt before the handshake fails.

Suggestion (hardening, not a vulnerability report). Parse the intermediates once per build_chain (for example into a Vec<Cert> up front, skipping or remembering the ones that fail to parse) and reuse the parsed certificates in each recursive step. That would make the per-call cost an issuer-name comparison rather than a full DER parse, without changing the budget semantics.

We are filing this as an enhancement idea only; we know the budget is a deliberate, tested design copied from mozilla::pkix, and we are not asking for a change to it.

Dominant language
Rust
Stars
167
Forks
112
Avg merge
4h 28m
Merged PRs (30d)
4

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from rustls/webpki

All issues in rustls/webpki

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.