Skip to content

Upgrade pingora to 0.8.0 (resolves 3 pingora-* CVEs)#3

Merged
raffaelschneider merged 39 commits into
mainfrom
upgrade-0.8.0
May 25, 2026
Merged

Upgrade pingora to 0.8.0 (resolves 3 pingora-* CVEs)#3
raffaelschneider merged 39 commits into
mainfrom
upgrade-0.8.0

Conversation

@raffaelschneider

@raffaelschneider raffaelschneider commented May 25, 2026

Copy link
Copy Markdown

Summary

Mirrors the zentinel-0.8.0 branch from raskell-io/pingora into this fork. 38 commits ahead of main, including the upstream pingora 0.8.0 release, our prometheus-protobuf fix, and an .cargo/audit.toml update for the three remaining dev-dep advisories.

What this PR resolves

After the bump and a fresh cargo audit, 0 vulnerabilities remain on this branch (7 informational warnings only — unmaintained/unsound, separate scope). All of the following are fixed by either the 0.8.0 code itself or by a natural resolver re-pick on a fresh Cargo.lock (lockfile is gitignored, CI regenerates it):

Advisory Crate How it gets fixed
RUSTSEC-2026-0035 pingora-cache Removed CacheKey::default impl on 0.8.0
RUSTSEC-2026-0034 pingora-core "Reject non-chunked transfer-encoding" + parsing robustness commits
RUSTSEC-2026-0033 pingora-core "Fix upgrade handling if body not init" + related
RUSTSEC-2026-0044..0048 aws-lc-sys Fresh resolver picks 0.41.0 (patched ≥0.39.0) via aws-lc-rs 1.17
RUSTSEC-2026-0037 quinn-proto Fresh resolver picks 0.11.14
RUSTSEC-2026-0099 rustls-webpki (prod) Fresh resolver picks 0.103.13
RUSTSEC-2026-0098 rustls-webpki (prod) Fresh resolver picks 0.103.13
RUSTSEC-2026-0104 rustls-webpki (prod) Fresh resolver picks 0.103.13
RUSTSEC-2026-0009 time Fresh resolver picks 0.3.47

What is explicitly ignored (and why)

Three advisories remain on rustls-webpki 0.101.7, pulled in only via the reqwest = "0.11" [dev-dependencies] entry in pingora-core, pingora-proxy, and pingora. These never ship in any library consumer's binary.

Advisory Reason ignored
RUSTSEC-2026-0098 rustls-webpki 0.101.x is unpatched (all fixes in ≥0.103.12). Fix path requires reqwest 0.11 → 0.12, which transitively requires hyper 0.14 → 1.0 in test code — a much larger upgrade.
RUSTSEC-2026-0099 Same.
RUSTSEC-2026-0104 Same.

These are documented in .cargo/audit.toml on this branch.

Merge conflict expected on .cargo/audit.toml

main currently has 7 stopgap ignores I added earlier (commit bfb3fda) to silence advisories that no longer apply once 0.8.0 lands. This branch instead carries 4 ignores (1 prometheus + 3 dev-dep rustls-webpki). Resolve the conflict by taking the branch's version — the 7 stopgap ignores on main are obsolete once this PR lands.

The ci(audit): fix push trigger branch and add workflow_dispatch workflow change on main (commit 9abfa72) should be preserved on merge — it doesn't conflict.

Test plan

  • CI green on this branch (build + tests).
  • cargo audit on merged tree: zero vulnerabilities (7 informational warnings expected).
  • Manual smoke: confirm CacheKey::default callers were already removed or updated downstream (callers must now provide a Host-header-inclusive key).
  • Follow-up: hyper 0.14 → 1.0 upgrade to retire the 3 dev-dep ignores.

gumpt and others added 30 commits February 10, 2026 08:55
Previously the body reader would initialize to HTTP/1.0 mode when the
upgrade request header is found. Now the reader is only converted to
that mode when both the upgrade header and 101 is received.
Because pipelining support is not yet fully implemented, pingora should
avoid trying to process any pipelined message read alongside the current
request. The session's connection will be closed and marked un-reusable.
Creates a pipe subrequest state machine utility to be able to treat the
subrequest as a "pipe" (sending request body and writing response tasks
directly from the subrequest).

Also adds a handler to be able to propagate the downstream / final proxy
error that a subrequest server session encounters to the pipe state
machine.

The subrequest pipe is also allowed to receive a preset input body,
which may also be created from a previously captured downstream session
body. In this case the captured session body may be reused for multiple
"chained" subrequests.

Co-authored-by: Matthew Gumport <mbg@cloudflare.com>
UpgradedBody was incorrectly no longer invoked for upstream response
body filters or for downstream modules. Additionally allow supporting
the rare case where UpgradedBody may be cached.
RFC9112 is now extra explicit about the close delimiting applying
exclusively to response messages for HTTP/1.0. Also disables reuse
explicitly when close delimiting on the response side as
defense-in-depth that shouldn't have behavioral diff.
The upgrade body mode changes also should be applied to subrequests
though upgrade and websockets are still highly experimental for them.
If a content-length is present RFC9112 indicates we must reject invalid
forms of that content-length header. This eliminates situations where we
might be dealing with ambiguous request framing.
Custom sessions need to report their upgrade state to the
proxy framework. Previously, Session::is_upgrade_req() and
Session::was_upgraded() always returned false for Custom sessions,
which broke WebSocket upgrade handling when using custom protocols.

This change:
- Adds is_upgrade_req() and was_upgraded() methods to the custom
  Session trait with default implementations returning false
- Updates the main Session enum to delegate to the custom session's
  implementation instead of returning false
This can be enabled via server options. Since CONNECT changes the
request-response flow separate from HTTP much like upgrade requests but
is currently unsupported, these requests will be automatically rejected
by default.
When a custom protocol is shutdown, it is passed
a numeric code. This should be 0 to indicate an
explicit shutdown rather than any other transport
error.
Anyone using caching must must now implement cache_key_callback themselves. This
forces an explicit decision about what belongs in the cache key for anyone using
thet trait for caching rather than providing an unsafe default that does not
support web standards.
If the body is not init when upgraded, there was an issue where the body
might be improperly ended early and the conn simply closed.
Rejecting bad upstream content-length by default to avoid forwarding
ambiguously framed messages. An option still exists to allow this
in the peer options, if needed, and treat these responses as
close-delimited though this is non-RFC-compliant.

The content-length is now also removed on the response if
transfer-encoding is present, per RFC.
…ket` impl

The `#[cfg(windows)] impl AsRawSocket for RawStream` was missing a match
arm for the `RawStream::Virtual(_)` variant, causing a compilation error
(E0004: non-exhaustive patterns) on Windows targets.

The `Virtual` variant is not gated by any `#[cfg]` attribute and exists
on all platforms, but the Windows `AsRawSocket` implementation only
matched `RawStream::Tcp(s)`.

This fix adds the missing arm, returning `!0` (INVALID_SOCKET) for
virtual streams, consistent with the Unix `AsRawFd` implementation
which returns `-1` for the same variant.

Co-authored-by: Cursor <cursoragent@cursor.com>
Includes-commit: 6da94f9
Replicated-from: cloudflare#809
The peer option wasn't always being applied when used with other
connectors like v2. Also clarify this is to support legacy behavior and
may be removed in the future.
justinrubek and others added 9 commits March 2, 2026 16:36
---
Merge branch 'cloudflare:main' into fix-socket-perms

Includes-commit: 7a748e7
Includes-commit: fdc2027
Replicated-from: cloudflare#810
`parse_range_header` was returning `RangeType::None` for the input
`"bytes="` (the bytes= prefix with no range-specs after it). Per RFC 9110
14.1.2, `"bytes="` is syntactically a range request with zero satisfiable
range-specs, so the correct response is 416 Range Not Satisfiable.

Added an early check for an empty/whitespace-only range-set after the
`bytes=` prefix, returning `RangeType::Invalid` instead of falling
through to the regex loop.
This removes {transfer,content}-encoding headers from 416 resonses. This
mirrors what to_304() in conditional_filter.rs already does for 304 Not
Modified responses.
…nerability

The prometheus crate's default features pull in the protobuf crate,
which has a known vulnerability (RUSTSEC-2024-0437). Pingora only uses
TextEncoder and gather() from prometheus — protobuf encoding is not
needed. Disabling default-features removes the vulnerable dependency.
After bumping to pingora 0.8.0, a fresh Cargo.lock naturally resolves
rustls-webpki 0.103.x, time, aws-lc-sys, and quinn-proto to clean
versions — no lockfile commits needed since Cargo.lock is gitignored
in this repo.

The only remaining advisories are on rustls-webpki 0.101.7, pulled in
exclusively as a transitive of the `reqwest = "0.11"` [dev-dependencies]
entry in pingora-core, pingora-proxy, and pingora. These cannot affect
any library consumer of pingora.

Patches for these advisories only exist in rustls-webpki >=0.103.12, so
ignoring them requires bumping reqwest 0.11 -> 0.12 in dev-deps. That
bump pulls http 1.0 and breaks 13 test assertions across
pingora-proxy/tests/{test_basic,test_upstream}.rs that interleave hyper
0.14 (http 0.2) types with reqwest response types. The clean fix is the
larger hyper 0.14 -> 1.0 upgrade, tracked separately.

Advisories:
  - RUSTSEC-2026-0098 rustls-webpki URI name constraints
  - RUSTSEC-2026-0099 rustls-webpki wildcard name constraints
  - RUSTSEC-2026-0104 rustls-webpki CRL parsing panic
@raffaelschneider raffaelschneider merged commit 13bb9f2 into main May 25, 2026
4 of 5 checks passed
@raffaelschneider raffaelschneider deleted the upgrade-0.8.0 branch May 25, 2026 08:52
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.