chore(deps): batch six renovate lockfile bumps + clear yanked spin - #452
Merged
Conversation
Consolidates the six open renovate PRs into one branch, following the precedent set by #435: one CI run and one review instead of six, and no Cargo.lock conflict cascade from merging them one at a time. All six are lockfile-only patch bumps within the existing Cargo.toml constraints — no manifest changes: | Crate | From → To | Was | |-----------------------|-----------------|------| | clap | 4.6.1 → 4.6.6 | #443 | | clap_complete | 4.6.7 → 4.6.9 | #447 | | clap_complete_nushell | 4.6.0 → 4.6.1 | #444 | | futures-util | 0.3.32 → 0.3.33 | #445 | | http-body-util | 0.1.3 → 0.1.4 | #446 | | keyring | 4.1.5 → 4.1.6 | #448 | clap_builder, clap_derive and the futures-core/io/macro/sink/task family move alongside their parents; the resulting diff is exactly the union of the six PRs with no extra crates picked up. Supersedes #443, #444, #445, #446, #447, #448 — those PRs need closing by hand, since GitHub's closing keywords apply to issues, not PRs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
mpecan
force-pushed
the
chore/renovate-batch-2026-08
branch
from
August 7, 2026 14:58
9b12269 to
1f57a4f
Compare
Contributor
Filter Verification ReportChanged FiltersNo filter files changed in this PR. All Filters Summary✅ 151/151 test cases passed across 51 filters Generated by |
Both versions in the lockfile were yanked from crates.io. Neither is reachable from a direct dependency — they arrive via axum -> multer and aws-sdk-s3 -> aws-smithy-checksums -> crc-fast — so nothing surfaced them until a supply-chain check went looking. Each has a non-yanked successor inside the same semver range, so this is a lockfile-only move with no manifest change: spin 0.9.8 -> 0.9.9 (via axum 0.8.9 -> multer 3.1.0) spin 0.10.0 -> 0.10.1 (via aws-sdk-s3 1.137.0 -> crc-fast 1.10.0) A yank is the mechanism by which a compromised release is withdrawn from crates.io, so sitting on yanked versions is worth clearing regardless of why these two were pulled. Found by `cargo deny check advisories`, which is being added to CI separately. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
mpecan
added a commit
that referenced
this pull request
Aug 7, 2026
Two asks, one branch: make renovate open a single batched PR, and harden dependency upgrades against compromised releases. > **Depends on #452.** The new `cargo deny` job fails on this branch alone, because `main` currently pins two **yanked** versions of `spin`. #452 clears them. Merge that first and this goes green; the failure is the new check doing its job. --- ## 1. Renovate: one PR instead of six | | Before | After | |---|---|---| | Cargo patch updates | one PR each | batched into a single `cargo dependencies` PR | | Cargo minor updates | grouped separately | same batch | | Major updates | individual | individual (unchanged) | | New release age | none — proposed within hours | **quarantined 7 days** | | Security fixes | same queue as everything | exempt from quarantine *and* schedule | | Automerge | configured, never fired | removed | **Batching.** The old config grouped only *minor* updates, so patch bumps — the overwhelming majority — each got a PR. Six were open when I started, all touching only `Cargo.lock`, so merging any one put the other five into conflict. **Quarantine.** `minimumReleaseAge: "7 days"` holds a new version back before proposing it. A compromised release is usually caught and yanked within a day or two; against the existing Monday schedule this costs no real latency. `vulnerabilityAlerts` overrides both the age and the schedule so security fixes come through immediately — a known-exploited hole is worse than an unvetted release. `osvVulnerabilityAlerts` adds the OSV database as a source for those. **Automerge removed.** It could never fire — see the analysis in #452. Rather than grant the bot a ruleset bypass, I dropped the dead config: auto-merging dependency bumps with nobody looking is precisely what the quarantine exists to prevent. If you'd rather have working automerge, say so and I'll add renovate as a bypass actor instead. Validated with `renovate-config-validator`. ## 2. cargo-deny gate New `supply-chain` CI job running `cargo deny check advisories bans sources`, wired into the aggregate `Check` job so it actually blocks. Policy in `deny.toml`: - **advisories** — RustSec reports, plus **yanked** crates. A yank is the mechanism by which a compromised release is withdrawn from crates.io. - **bans** — wildcard version requirements, which accept any future release sight-unseen. - **sources** — crates.io only. A dependency that suddenly resolves to a git repository is the shape a takeover attack takes, and would otherwise pass unnoticed in a lockfile diff. It found something on its first run: two yanked `spin` versions, reached indirectly via `axum → multer` and `aws-sdk-s3 → crc-fast`. Fixed in #452. One caveat, documented in `deny.toml`: dev-dependencies are excluded from the graph. `crates/tokf-server` dev-depends on **itself** under an alias to enable its `test-helpers` feature, and `krates` (inside cargo-deny 0.20.2) hits an `unreachable!()` on that node. Worth revisiting when that's fixed upstream. ## 3. Actions pinned to commit SHAs All 17 actions now use a full SHA with the version in a trailing comment. **Three were on `@master`** — `dtolnay/rust-toolchain` (×5) and `superfly/flyctl-actions` — where whoever controls that repository can repoint the ref at new code, which then runs here with our token and cache. This is the `tj-actions/changed-files` attack class. Two of these derive their behaviour from the *ref name*: `dtolnay/rust-toolchain@stable` and `taiki-e/install-action@nextest` read the ref to pick a default. The defaults turn out to be baked into `action.yml` at each pinned SHA (verified), so pinning alone doesn't break them — but I've made `toolchain:` and `tool:` explicit anyway, since relying on that would break silently on a future re-pin. Renovate keeps the digests current via `helpers:pinGitHubActionDigests`. ## 4. Checkout credentials and permissions **`persist-credentials: false`** on all 13 checkouts that don't push. Without it the token is left in `.git/config`, where a `build.rs` or proc macro compiled later in the same job can read it — a real concern for a Rust repo, where every build executes third-party code. The two Homebrew tap checkouts in `release.yml` are exempt because they push with those credentials, and now carry a comment saying so. **Explicit `permissions:`** on the three workflows that had none. The repo default is already read-only, so no behaviour changes today — this stops a future change to that default from silently widening them. `verify-comment.yml` gets the tightest treatment as the one genuinely privileged workflow: it runs via `workflow_run` in the base repo with secrets even for fork PRs, so GITHUB_TOKEN gets only `contents: read` + `actions: read`, and the comment is posted with a scoped app token. **`--locked`** on every cargo invocation, so CI fails rather than silently resolving versions differing from `Cargo.lock`. ## Verification - All nine workflows parse; **no duplicate keys** (checked with a strict YAML loader, not just `safe_load`) - No mutable action refs remain - Every cargo invocation carries `--locked` - `renovate-config-validator` — passes - `cargo deny check advisories bans sources` — `bans ok, sources ok`; advisories pass once #452 lands - `cargo clippy --workspace --all-targets -- -D warnings` and `cargo test --workspace` (2468 passed) — unaffected, no Rust changes ## Not done - **`sha_pinning_required`** is available as a repo setting (currently off) and would enforce rule 3 for good. Not flipped — it's a repo setting, not a file, and it's your call. - **`cargo vet` / `cargo crev`** — crate-level review attestations. Materially more process; deferred. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Batches the six open renovate PRs into one branch — one CI run, one review, and no
Cargo.lockconflict cascade from merging them sequentially. Same approach as #435. Also clears two yanked crates found while adding supply-chain checks.Taken — the six renovate PRs
No
Cargo.tomlchanges — every bump fits the existing constraints.clap_builder,clap_deriveand thefutures-core/io/macro/sink/taskfamily move with their parents; the diff is exactly the union of the six PRs, no extra crates picked up.Also taken — two yanked crates (second commit)
Both versions had been yanked from crates.io. Neither is reachable from a direct dependency, so nothing surfaced them until
cargo deny check advisorieswent looking (that check is being added in a separate PR). Each has a non-yanked successor inside the same semver range, so this is lockfile-only too.A yank is the mechanism by which a compromised release gets withdrawn, so sitting on yanked versions is worth clearing regardless of why these two were pulled.
Why batch instead of merging the six
All six touch only
Cargo.lock. Merging any one makes the other five conflict, and renovate only rebases inside its schedule window (before 6am on monday) — so merging them one at a time would have spread across several weeks.Why they were stuck
Renovate had already enabled squash auto-merge on all six on the day it opened them. They sat at
mergeStateStatus: BLOCKED/reviewDecision: REVIEW_REQUIRED, because therequire-pr-approvalruleset requires one approving review and renovate cannot approve its own PR. Its bypass actor is the admin repository role, which renovate does not hold. Theautomerge: truerule for cargo patch updates in.github/renovate.jsoncan therefore never fire — every patch bump keeps piling up until someone batches it by hand. Addressed in the follow-up hardening PR.The two red PRs (#443, #447) were not real failures — both were GitHub Actions infrastructure flakes (
Failed to resolve action download info. Error: Service Unavailable). I re-ran them and they went green.Verification
cargo clippy --workspace --all-targets -- -D warnings— cleancargo test --workspace— 2468 passed, 0 failed, 180 ignoredcargo deny check advisories bans sources— passes with the spin fix; failed on both yanked versions without itSuperseded PRs
Supersedes #443, #444, #445, #446, #447, #448. GitHub's closing keywords only auto-close issues, not PRs, so those six need closing by hand after this merges — or renovate will autoclose them itself on its next scheduled run (Monday before 6am).
🤖 Generated with Claude Code