Skip to content

chore: bump deps and resolve all 46 security alerts - #28

Merged
nihaopaul merged 1 commit into
mainfrom
chore/security-and-dep-updates
Aug 22, 2026
Merged

chore: bump deps and resolve all 46 security alerts#28
nihaopaul merged 1 commit into
mainfrom
chore/security-and-dep-updates

Conversation

@nihaopaul

@nihaopaul nihaopaul commented Aug 22, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds a cargo build + test CI job triggered on pull_request so future dependabot PRs get compile verification (previously CI only ran on release events)
  • Applies all 5 open dependabot PRs (Bump thiserror from 2.0.16 to 2.0.17 #23 thiserror, Bump serde from 1.0.219 to 1.0.228 #24 serde, Bump axum from 0.8.4 to 0.8.6 #25 axum, Bump reqwest from 0.12.23 to 0.12.24 #26 reqwest, Bump tokio from 1.47.1 to 1.48.0 #27 tokio) — closes them all
  • Upgrades jsonwebtoken 9.3.0 → 10.4.0 in cloudflare-authenticator to fix CVE type-confusion auth bypass (required a major version bump)
  • Runs cargo update to pull in patched transitive versions, resolving all 46 open security alerts:
    • openssl 0.10.72 → 0.10.81 (7 CVEs: OOB write, heap overflow, undefined behaviour, memory leak)
    • rustls-webpki 0.102.8 → 0.103.15 (3 CVEs: DoS, name constraint bypass)
    • bytes 1.9.0 → 1.12.1 (integer overflow)
    • time 0.3.37 → 0.3.55 (stack exhaustion DoS)
    • rand 0.8.5 → 0.9.5 (unsound with custom logger)

Verified with a clean cargo build locally.

Test plan

  • CI build job passes (cargo build + test)
  • Confirm dependabot security alerts drop to zero after merge

Closes #23, #24, #25, #26, #27

🤖 Generated with Claude Code

Applies all 5 open dependabot PRs (#23-#27) and upgrades jsonwebtoken
from 9.3.0 to 10.x to fix CVE type-confusion auth bypass. cargo update
then pulled in patched transitive versions: openssl 0.10.81 (7 CVEs),
rustls-webpki 0.103.15 (3 CVEs), bytes 1.12.1, time 0.3.55, rand 0.9.5.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@nihaopaul
nihaopaul merged commit 12f255a into main Aug 22, 2026
4 checks passed
@nihaopaul
nihaopaul deleted the chore/security-and-dep-updates branch August 22, 2026 08:37
nihaopaul added a commit that referenced this pull request Aug 22, 2026
* Build a static musl release image and fix JWT crypto provider

The release image compiled against glibc from `rust:1` but ran on
distroless/cc-debian12. `rust:1` now tracks Debian 13, so that pairing was
one base-image bump away from a GLIBC_* load failure. Switch to a fully
static musl binary on distroless/static-debian13, removing the glibc
version-matching constraint entirely (~25MB -> 12.3MB).

Linking statically forced OpenSSL out of the tree, which was worth doing
anyway: reqwest pulled in both native-tls/OpenSSL (via default features)
and rustls, so two TLS stacks were compiled in and only one was used. Now
rustls-only. `http2` and `charset` are re-enabled explicitly because
`default-features = false` silently drops them.

Fix a live bug found along the way: jsonwebtoken 10 ships no crypto
provider by default (`default = ["use_pem"]`), so decode() in
Authenticator::decode panicked instead of verifying -- the core path of
the service. Enable `rust_crypto`, which is also the pure-Rust backend
that keeps the static build free of new C dependencies.

CI never caught that because the sub-crates were not workspace members,
so `cargo test` at the root only ran the root package's zero tests. Add a
[workspace] table and pass --workspace in CI; the three existing sub-crate
tests now actually run. That also collapses three independently resolved
lockfiles into one and lets mockito -- a test HTTP server that was being
compiled into the production binary -- move to [dev-dependencies].

Exclude .devbox from the Docker build context: it is 1.3GB and self-ignores
via a nested .gitignore that .dockerignore does not honour, which
hard-failed local image builds.

Verified on a live system: aarch64 static binary (no interpreter, no GLIBC_
symbols, zero OpenSSL strings), runs on distroless/static, fetches the
Access JWKS and the Cloudflare API over rustls using baked-in webpki roots,
and rejects malformed and unsigned JWTs with 403 without panicking.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Add devbox configuration and include devbox.lock in .gitignore

* Make JWT validation actually tested, and pin alg to the JWKS

PR #28 bumped jsonwebtoken 9.3.0 -> 10 without selecting a crypto
backend. v10 made that choice mandatory, so every decode() call panicked
instead of verifying. 3fbb7b9 enabled `rust_crypto`; this commit addresses
why the regression reached main unnoticed.

Both authenticator tests asserted tautologies:

    assert_eq!(test.is_ok(), !test.is_err());
    assert_eq!(test.is_err(), !test.is_ok());

Neither can fail for any Result. The "success" test could not have passed
on its own terms regardless: its token expired 2025-01-29, and every
audience in its expected list was the real value with the leading
character truncated, so validation returned Err while the assertion still
held.

Replace them with six tests that mint a throwaway RSA keypair per run and
sign tokens at test time, so no token ages into a false failure and no
private key is committed. They cover the accept path plus expiry,
audience mismatch, unknown kid and missing kid.

Also stop taking the algorithm from the token header. Validation::new(
header.alg) lets a caller nominate the algorithm their own signature is
checked against. jsonwebtoken blocks cross-family swaps (RSA vs HMAC), so
this was not exploitable, but a token signed RS384 against an RS256 JWKS
was accepted. Use the algorithm the JWKS advertises instead. The
regression test for this was confirmed to fail on the old line and pass
on the new one.

Drop the .unwrap() on DecodingKey::from_rsa_components, which could panic
inside a request handler given a malformed JWKS.

Point the placeholder devbox `test` script at the real suite and add a
matching `build` script.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Clear clippy across the workspace and commit devbox.lock

Clippy reported 10 warnings across the three crates; all were needless
borrows, redundant returns or a redundant import. Now zero.

Two of them removed real work rather than just noise: fetch_apps cloned
`config.api` into a format! argument and cloned `config.token` for every
bearer_auth call, so each outbound request allocated two throwaway
Strings. Both are borrows now.

Also un-ignore devbox.lock. It is 1.9K of nix pins with no secrets, and
committing it makes `devbox run` resolve the same toolchain for everyone,
same rationale as Cargo.lock. Without it the environment is only pinned as
far as "stable".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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.

1 participant