Migrate rand 0.8 to 0.10, and test the two values it generates - #6
Merged
Merged
Conversation
This was referenced Sep 14, 2026
mattpodwysocki
force-pushed
the
rand-0-10
branch
from
September 14, 2026 17:39
62ed945 to
4396f8b
Compare
zmofei
approved these changes
Sep 14, 2026
zmofei
left a comment
Member
There was a problem hiding this comment.
Small, well-scoped diff. Verified the Cargo.lock change is a genuine dedup (quinn-proto already pulled rand 0.10.2 via reqwest) removing 6 crates with nothing added. The two call-site renames preserve the CSPRNG guarantee (checked against rand's TryCryptoRng docs, not assumed). New tests cover generate_pkce and the OAuth state, previously untested — and the author validated the distinctness test actually catches a broken generator (verified with a fixed [7u8; 32] substitution). CI green. No issues found.
**It removes six crates and adds none.** The lock already carried rand 0.10.2, because `quinn-proto` needs it through reqwest — so `rand = "0.8"` was forcing a second, older copy alongside it. Migrating deduplicates onto the version already in the graph and drops 0.8's exclusive subtree: `rand@0.8.8`, `rand_chacha@0.3.1`, `rand_core@0.6.4`, `ppv-lite86@0.2.21`, `zerocopy@0.8.57`, `zerocopy-derive@0.8.57`. 207 packages to 201. The code change is two call sites in `auth.rs`, both renames: `thread_rng()` is now `rng()`, and `Rng::gen` is `random()`. `rand::random` is a free function, so the `use rand::Rng` import goes away rather than becoming `RngExt`. **The randomness guarantee is unchanged and now stated.** Both values — the PKCE verifier and the OAuth `state` — draw from `ThreadRng`, which rand 0.10 declares `TryCryptoRng`, the same CSPRNG guarantee 0.8's `thread_rng` gave. Checked in rand's source rather than assumed, because it is the property these two strings live or die by. **Nothing tested either of them before.** `generate_pkce` had no test at all. Four now: the pair satisfies RFC 7636 §4.1 and §4.2 (43 characters, and the challenge really is `BASE64URL(SHA256(ASCII(verifier)))` rather than a hash of the raw bytes), both strings use only the unreserved alphabet because they go into a query string unescaped, successive pairs differ, and the `state` parameter is covered too. That last one is the one that matters, and it fails for the right reason: replacing the generator with `[7u8; 32]` leaves the length and alphabet tests passing — a constant is perfectly well-formed — and only `every_pkce_pair_is_different` goes red. Ported from mapbox/mapbox-cli-private#139, which cannot merge there now that `oss/` is a submodule (mapbox/mapbox-cli-private#132). It exists because Dependabot tried this by moving the lockfile alone, which fails every `--locked` build while the manifest still says `rand = "0.8"`.
mattpodwysocki
force-pushed
the
rand-0-10
branch
from
September 14, 2026 18:04
4396f8b to
c35f0dc
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ported from mapbox-cli-private#139, which can no longer merge there now that
oss/is a submodule (#132). CI was green there; re-verified here.It exists because Dependabot tried this by moving the lockfile alone, which cannot work:
Cargo.tomldeclaredrand = "0.8", so a lock pinning 0.10.2 fails every--lockedinvocation withcannot update the lock file because --locked was passed. The private repo'sdependabot.ymlnames this case exactly — "a semver-major step — clap 5, rand 0.9 — is a person's decision made in its own PR".It removes six crates and adds none
The best argument for the migration, and I didn't expect it. The lock already carried rand 0.10.2, because
quinn-protoneeds it through reqwest — sorand = "0.8"was forcing a second, older copy alongside it. Migrating deduplicates onto the version already in the graph and drops 0.8's exclusive subtree:rand@0.8.8,rand_chacha@0.3.1,rand_core@0.6.4,ppv-lite86@0.2.21,zerocopy@0.8.57,zerocopy-derive@0.8.57(
.gitattributesmarks*.lock -diff, so the lockfile shows as binary in review. I compared the two as name@version sets rather than reading the diff — worth knowing, becausecommon the raw name lists gives a wrong answer here:randappears twice in the old lock, and dedup makes the naive diff look like the dependency was deleted outright.)There was no urgency behind it: the advisories check passes on 0.8.8, so nothing shipped is vulnerable. The 0.10.1 soundness fix and 0.10.2 memory-safety fix don't apply to the version we were on.
The code change is two renames
thread_rng()→rng(), andRng::gen→random().rand::randomis a free function, souse rand::Rnggoes away rather than becomingRngExt.The randomness guarantee is unchanged, and now written down. Both values — the PKCE verifier and the OAuth
state— draw fromThreadRng, which rand 0.10 declaresTryCryptoRng: the same CSPRNG guarantee 0.8'sthread_rnggave. I checked that in rand's source rather than assuming it, because it is the one property these two strings live or die by, and the comment now says so next to each.Nothing tested either of them before
generate_pkcehad no test at all, so the suite had nothing to say about migrating the crate that produces it. Four now:BASE64URL(SHA256(ASCII(verifier)))rather than a hash of the raw bytes behind the encoding.+,/or=would arrive meaning something else.stateparameter — same generator; a predictable one is a CSRF hole rather than a cosmetic flaw.I checked the important one fails for the right reason rather than trusting a green tick: replacing the generator with
[7u8; 32]leaves the length and alphabet tests passing — a constant is perfectly well-formed and perfectly URL-safe — and onlyevery_pkce_pair_is_differentgoes red. That is the botched migration a reviewer would otherwise have to catch by eye, and the reason the other three are not sufficient alone.Verified
cargo clippy --locked --all-targetsclean — the check the Dependabot attempt fails. 543 tests, fmt clean, and the 46 existingauth::tests still pass.