Skip to content

Release/0.5.7#16

Merged
talagrand merged 5 commits into
mainfrom
release/0.5.7
Jun 1, 2026
Merged

Release/0.5.7#16
talagrand merged 5 commits into
mainfrom
release/0.5.7

Conversation

@talagrand

Copy link
Copy Markdown
Owner

Fixed

  • Secret redaction: Debug output for Url and Proxy (and Error, transitively) now redacts the URL password and proxy Basic-auth password. Display already omitted them where provided.
  • URL parsing: winhttp_crack_url previously used fixed-size buffers for URL parts - these are now preserved in full.
  • 32-bit soundness: Return failure instead of wrapping if returned bodies would overflow usize.
  • 32-bit soundness: Return failure instead of silently truncating oversized inputs.
  • Retry budget: the slot-advance loop is now capped at the bucket count, so a long suspend (sleep, debugger, etc.) can no longer cause huge numbers of zero-bucket iterations on the next request.
  • DLL-host safety: closed path where a panic during HANDLE_CLOSING callback bookkeeping could be swallowed and leave WinHttpRequestHandle::drop hanging in wait_closed_and_idle.
  • Cross-origin redirects no longer forward Authorization, Cookie, Cookie2, Proxy-Authorization, Proxy-Authenticate, or WWW-Authenticate headers to the new origin. WinHTTP forwards these unchanged by default and documents that stripping them is the application's responsibility (Security Considerations item 16).
  • An https:// -> http:// redirect now returns Error::is_redirect() == true instead of silently surfacing the 3xx response. The Err shape matches what reqwest produces under https_only(true), but wrest applies it unconditionally: WinHTTP defaults to blocking the downgrade and wrest preserves that default, so the new shape is always what callers see (reqwest's default follows https->http silently).
  • URL path traversal: Url::join() now treats %2e / %2E as . when collapsing dot-segments, so an attacker-controlled relative reference like %2e%2e/secret can no longer escape a trusted base.

Changed

  • CI - Reliability: swap httpbin.org for a locally-hosted version for reliability (doesn't affect local testing)
  • Enabled clippy's cast_possible_truncation, cast_possible_wrap, cast_sign_loss, and arithmetic_side_effects lints (warn) to guard against integer-overflow and 32-bit soundness regressions.

…TTP edge cases

Turn on four Clippy lints crate-wide:
  cast_possible_truncation, cast_possible_wrap,
  cast_sign_loss, arithmetic_side_effects

This covers integer arithmetic soundness issues.
Rewrites some logic to avoid possible issues and marks others with
safety guarantees.

Enabling clippy's  lints surfaced several real bugs across the WinHTTP path as well:

* URL parsing no longer truncates long components. winhttp_crack_url used
  fixed 2 KiB host / 8 KiB path / 8 KiB query buffers and silently dropped
  anything longer. It now reads the in-place pointers WinHTTP writes back
  into the input UTF-16, so components are bounded only by the URL length.

* Response body collection returns Error::body("response body too large")
  if the accumulated length would overflow usize, instead of wrapping.
  Primarily matters on 32-bit targets where usize is u32.

* Retry budget can no longer spin millions of iterations after a long
  suspend (sleep, debugger). The slot-advance loop is now capped
  at slots-count iterations.

* WinHTTP callback bookkeeping no longer has a path where a panic during
  the HANDLE_CLOSING handler could be swallowed by catch_unwind and leave
  WinHttpRequestHandle::drop hanging in wait_closed_and_idle. The retained
  context is released before signalling, and the active-callback counter
  uses checked_add / checked_sub.

* MultiByteToWideChar wrapper clamps `written` against capacity before
  set_len, closing a theoretical UB window if Win32 ever overreported.

* WinHTTP header / read / write FFI surface oversize inputs as
  Error::request / Error::body instead of silently truncating via `as u32`
  (header lines > u32::MAX chars, write buffers > 4 GiB, etc.).

Copilot AI 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.

Pull request overview

This PR prepares the 0.5.7 release by tightening security behavior around redirects and secret redaction, improving WinHTTP URL parsing correctness, and hardening multiple code paths for 32-bit/overflow soundness and reliability.

Changes:

  • Add type-level secret redaction for Debug output (URL/proxy passwords, cascading into Error).
  • Harden redirect handling (strip sensitive headers on cross-origin redirects; surface https→http downgrade as a redirect-policy error).
  • Improve 32-bit/overflow robustness (checked length arithmetic, safer casts, retry budget loop cap, WinHTTP CrackUrl buffer preservation) and update CI/test reliability settings.

Reviewed changes

Copilot reviewed 25 out of 26 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/url_parse.rs Updates RFC-clean URL test commentary to reflect dot-segment/%2e behavior expectations.
tests/real_world.rs Increases test timeouts and adds redirect-policy parity tests for https→http downgrades.
tests/integration.rs Adjusts streaming upload test to avoid truncating casts.
src/winhttp.rs Adds cross-origin redirect header stripping, callback abort plumbing, overflow guards, and write/read size handling changes.
src/util.rs Removes an attribute previously suppressing dead-code warnings around wide-string conversion.
src/url.rs Redacts URL passwords in Debug, adjusts percent-decoding, and hardens dot-segment removal to treat %2e/%2E as dot tokens.
src/timer.rs Simplifies timer arming by passing Duration to the threadpool timer wrapper.
src/threadpool.rs Changes timer API to accept Duration and centralizes 100ns tick conversion with saturation.
src/retry.rs Caps slot-advance work, improves 32-bit conversions, and uses saturating arithmetic for writer accounting.
src/response.rs Prevents usize overflow while collecting response bodies (returns Error::body).
src/request.rs Uses explicit secret exposure when building Basic auth from URL userinfo.
src/redact.rs Introduces Redacted<T> newtype to redact secrets from Debug output.
src/proxy.rs Redacts proxy Basic-auth passwords in Debug by storing them as Redacted<String>.
src/lib.rs Wires in the new redact module for the native WinHTTP backend.
src/error.rs Adds Error::redirect, improves Win32 error conversion, and adds tests for redaction behavior in Debug.
src/encoding.rs Minor comment/implementation adjustments in decoder helpers.
src/client.rs Translates silently-surfaced https→http blocked redirects into redirect-policy errors; tracks whether redirects are followed.
src/abi/winhttp.rs Adds header removal helper, improves size handling at FFI boundaries, and preserves full URL part lengths in WinHttpCrackUrl.
src/abi/mod.rs Adds a dword_size_of<T>() helper for Win32 DWORD size casts.
src/abi/encoding.rs Adds empty-input fast-path and tighter bounds checks around Win32/ICU transcoding.
examples/whirl.rs Uses saturating arithmetic for download progress counters.
examples/hn_live.rs Uses saturating arithmetic and elapsed-time loop control for robustness.
examples/github_api.rs Uses saturating arithmetic for display numbering.
CHANGELOG.md Adds 0.5.7 release notes.
Cargo.toml Bumps version to 0.5.7 and enables additional clippy overflow/cast lints.
Cargo.lock Updates lockfile for the 0.5.7 release and dependency bumps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/winhttp.rs Outdated
Comment thread src/client.rs
Wrap Url::password and Proxy basic-auth password in a new
Redacted<T> type so `{:?}` (and transitively Error::Debug, panic
messages, dbg!, and tracing ?-formatters) no longer leak
credentials. Display was already userinfo-free.
@codecov

codecov Bot commented Jun 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.94737% with 8 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/abi/encoding.rs 90.00% 3 Missing ⚠️
src/abi/winhttp.rs 94.23% 3 Missing ⚠️
src/client.rs 96.55% 1 Missing ⚠️
src/winhttp.rs 99.76% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copilot AI 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.

Pull request overview

Copilot reviewed 25 out of 26 changed files in this pull request and generated 4 comments.

Comment thread src/winhttp.rs
Comment thread CHANGELOG.md
Comment thread tests/real_world.rs
Comment thread tests/real_world.rs
talagrand added 3 commits June 1, 2026 01:56
Cross-origin redirects no longer forward Authorization, Cookie,
Cookie2, Proxy-Authorization, Proxy-Authenticate, or WWW-Authenticate
to the new origin. Previously WinHTTP forwarded these unchanged
(documented behavior per Security Considerations item 16), so a
victim.example -> attacker.example 302 would deliver caller credentials
to the attacker host.

A redirect from https:// to http:// now returns an Err where
is_redirect() is true, instead of silently surfacing the 3xx response.
Most callers check is_success() or unwrap_or on .text() and would not
have noticed the downgrade; the new shape matches reqwest.
RFC 3986 §6.2.2.2 normalizes percent-encoded unreserved chars to their
literal form before §5.2.4 runs. join() previously matched only literal
"." / "..", so "%2e%2e/secret" against a trusted base traversed out on
the wire. Classify segments via strip_dot_token() so any mix of ".",
"%2e", "%2E" collapses; "%2f" stays encoded (segment byte, not
separator). Trailing slash now keyed on "last segment was a dot" so
/foo/%2e behaves like /foo/.

Copilot AI 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.

Pull request overview

Copilot reviewed 25 out of 26 changed files in this pull request and generated 3 comments.

Comment thread src/winhttp.rs
Comment thread tests/real_world.rs
Comment thread tests/real_world.rs
@talagrand talagrand merged commit dd10323 into main Jun 1, 2026
37 of 40 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.

2 participants