c227d76df42e8c3aed51dfd083eac8e5ed6cfcdf
7
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3b0b5558eb |
Update Rust crate jsonwebtoken to v10 [SECURITY] (#48294)
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [jsonwebtoken](https://redirect.github.com/Keats/jsonwebtoken) | workspace.dependencies | major | `9.3` → `10.0` | --- > [!WARNING] > Some dependencies could not be looked up. Check the Dependency Dashboard for more information. ### GitHub Vulnerability Alerts #### [GHSA-h395-gr6q-cpjc](https://redirect.github.com/Keats/jsonwebtoken/security/advisories/GHSA-h395-gr6q-cpjc) ## Summary: It has been discovered that there is a Type Confusion vulnerability in jsonwebtoken, specifically, in its claim validation logic. When a standard claim (such as nbf or exp) is provided with an incorrect JSON type (Like a String instead of a Number), the library’s internal parsing mechanism marks the claim as “FailedToParse”. Crucially, the validation logic treats this “FailedToParse” state identically to “NotPresent”. This means that if a check is enabled (like: validate_nbf = true), but the claim is not explicitly marked as required in required_spec_claims, the library will skip the validation check entirely for the malformed claim, treating it as if it were not there. This allows attackers to bypass critical time-based security restrictions (like “Not Before” checks) and commit potential authentication and authorization bypasses. ## Details: The vulnerability stems from the interaction between the TryParse enum and the validate function in [src/validation.rs](https://redirect.github.com/Keats/jsonwebtoken/blob/master/src/validation.rs). 1. The TryParse Enum: The library uses a custom TryParse enum to handle claim deserialization: ``` enum TryParse<T> { Parsed(T), FailedToParse, // Set when deserialization fails (e.g. type mismatch) NotPresent, } ``` If a user sends {“nbf”: “99999999999”} (legacy/string format), serde fails to parse it as u64, and it results in TryParse::FailedToParse. 1. The Validation Logic Flaw (src/validation.rs): In Validation::validate, the code checks for exp and nbf like this: ``` // L288-291 if matches!(claims.nbf, TryParse::Parsed(nbf) if options.validate_nbf && nbf > now + options.leeway) { return Err(new_error(ErrorKind::ImmatureSignature)); } ``` This matches! macro explicitly looks for TryParse::Parsed(nbf). • If claims.nbf is FailedToParse, the match returns false. • The if block is skipped. • No error is returned. 1. The “Required Claims” Gap: The only fallback mechanism is the “Required Claims” check: ``` // Lines 259-267 for required_claim in &options.required_spec_claims { let present = match required_claim.as_str() { "nbf" => matches!(claims.nbf, TryParse::Parsed(_)), // ... }; if !present { return Err(...); } } ``` If “nbf” IS in required_spec_claims, FailedToParse will fail the matches!(..., Parsed(_)) check, causing the present to be false, and correctly returning an error. However, widely accepted usage patterns often enable validation flags (validate_nbf = true) without adding the claim to the required list, assuming that enabling validation implicitly requires the claim’s validity if it appears in the token. jsonwebtoken seems to violate this assumption. Environment: • Version: jsonwebtoken 10.2.0 • Rust Version: rustc 1.90.0 • Cargo Version: cargo 1.90.0 • OS: MacOS Tahoe 26.2 POC: For demonstrating, Here is this simple rust code that demonstrates the bypass. It attempts to validate a token with a string nbf claiming to be valid only in the far future. create a new project: ``` cargo new nbf_poc; cd nbf_poc ``` add required dependencies: ``` cargo add serde --features derive cargo add jsonwebtoken --features rust_crypto cargo add serde_json ``` replace the code in src/main.rs with this: ``` use jsonwebtoken::{decode, Validation, Algorithm, DecodingKey, Header, EncodingKey, encode}; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] struct Claims { sub: String, nbf: String, // Attacker sends nbf as a String exp: usize, } fn main() { let key: &[u8; 24] = b"RedMouseOverTheSkyIsBlue"; // nbf is a String "99999999999" (Far future) // Real nbf should be a Number. let my_claims: Claims = Claims { sub: "krishna".to_string(), nbf: "99999999999".to_string(), exp: 10000000000, }; let token: String = encode(&Header::default(), &my_claims, &EncodingKey::from_secret(key)).unwrap(); println!("Forged Token: {}", token); // 2. Configure Validation let mut validation: Validation = Validation::new(Algorithm::HS256); validation.validate_nbf = true; // Enable NBF check // We do NOT add "nbf" to required_spec_claims (default behavior) // We decode to serde_json::Value to avoid strict type errors in our struct definition hiding the library bug. // The library sees the raw JSON with string "nbf". let result: Result<jsonwebtoken::TokenData<serde_json::Value>, jsonwebtoken::errors::Error> = decode::<serde_json::Value>( &token, &DecodingKey::from_secret(key), &validation ); match result { Ok(_) => println!("Token was accepted despite malformed far-future 'nbf'!"), Err(e) => println!("Token rejected. Error: {:?}", e), } } ``` run cargo run expected behaviour: ``` Forged Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJrcmlzaG5hIiwibmJmIjoiOTk5OTk5OTk5OTkiLCJleHAiOjEwMDAwMDAwMDAwfQ.Fm3kZIqMwqIA6sEA1w52UOMqqnu4hlO3FQStFmbaOwk ``` Token was accepted despite malformed far-future 'nbf'! Impact: If an application uses jsonwebtoken nbf (Not Before) to schedule access for the future (like “Access granted starting tomorrow”). By sending nbf as a string, an attacker can bypass this restriction and access the resource immediately. and for the exp claim (this is unlikely but still adding), If a developer sets validate_exp = true but manually handles claim presence (removing exp from required_spec_claims), an attacker can send a string exp (e.g., “never”) and bypass expiration checks entirely. The token becomes valid forever. --- ### Release Notes <details> <summary>Keats/jsonwebtoken (jsonwebtoken)</summary> ### [`v10.3.0`](https://redirect.github.com/Keats/jsonwebtoken/blob/HEAD/CHANGELOG.md#1030-2026-01-27) [Compare Source](https://redirect.github.com/Keats/jsonwebtoken/compare/v10.2.0...v10.3.0) - Export everything needed to define your own CryptoProvider - Fix type confusion with exp/nbf when not required ### [`v10.2.0`](https://redirect.github.com/Keats/jsonwebtoken/blob/HEAD/CHANGELOG.md#1020-2025-11-06) [Compare Source](https://redirect.github.com/Keats/jsonwebtoken/compare/v10.1.0...v10.2.0) - Remove `Clone` bound from decode functions ### [`v10.1.0`](https://redirect.github.com/Keats/jsonwebtoken/blob/HEAD/CHANGELOG.md#1010-2025-10-18) [Compare Source](https://redirect.github.com/Keats/jsonwebtoken/compare/v10.0.0...v10.1.0) - add `dangerous::insecure_decode` - Implement TryFrom \&Jwk for DecodingKey ### [`v10.0.0`](https://redirect.github.com/Keats/jsonwebtoken/blob/HEAD/CHANGELOG.md#1000-2025-09-29) [Compare Source](https://redirect.github.com/Keats/jsonwebtoken/compare/v9.3.1...v10.0.0) - BREAKING: now using traits for crypto backends, you have to choose between `aws_lc_rs` and `rust_crypto` - Add `Clone` bound to `decode` - Support decoding byte slices - Support JWS </details> --- ### Configuration 📅 **Schedule**: Branch creation - "" in timezone America/New_York, Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- Release Notes: - N/A <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi45NS4yIiwidXBkYXRlZEluVmVyIjoiNDIuOTUuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Marshall Bowers <git@maxdeviant.com> |
||
|
|
5a5b5ae2bb |
Remove workspace-hack (#40216)
We've been considering removing workspace-hack for a couple reasons: - Lukas ran into a situation where its build script seemed to be causing spurious rebuilds. This seems more likely to be a cargo bug than an issue with workspace-hack itself (given that it has an empty build script), but we don't necessarily want to take the time to hunt that down right now. - Marshall mentioned hakari interacts poorly with automated crate updates (in our case provided by rennovate) because you'd need to have `cargo hakari generate && cargo hakari manage-deps` after their changes and we prefer to not have actions that make commits. Currently removing workspace-hack causes our workspace to grow from ~1700 to ~2000 crates being built (depending on platform), which is mainly a problem when you're building the whole workspace or running tests across the the normal and remote binaries (which is where feature-unification nets us the most sharing). It doesn't impact incremental times noticeably when you're just iterating on `-p zed`, and we'll hopefully get these savings back in the future when rust-lang/cargo#14774 (which re-implements the functionality of hakari) is finished. Release Notes: - N/A |
||
|
|
6f2725844a |
Use anyhow more idiomatically (#31052)
https://github.com/zed-industries/zed/issues/30972 brought up another case where our context is not enough to track the actual source of the issue: we get a general top-level error without inner error. The reason for this was `.ok_or_else(|| anyhow!("failed to read HEAD SHA"))?; ` on the top level. The PR finally reworks the way we use anyhow to reduce such issues (or at least make it simpler to bubble them up later in a fix). On top of that, uses a few more anyhow methods for better readability. * `.ok_or_else(|| anyhow!("..."))`, `map_err` and other similar error conversion/option reporting cases are replaced with `context` and `with_context` calls * in addition to that, various `anyhow!("failed to do ...")` are stripped with `.context("Doing ...")` messages instead to remove the parasitic `failed to` text * `anyhow::ensure!` is used instead of `if ... { return Err(...); }` calls * `anyhow::bail!` is used instead of `return Err(anyhow!(...));` Release Notes: - N/A |
||
|
|
ec4babbf14 |
Add workspace-hack (#27277)
This adds a "workspace-hack" crate, see [mozilla's](https://hg.mozilla.org/mozilla-central/file/3a265fdc9f33e5946f0ca0a04af73acd7e6d1a39/build/workspace-hack/Cargo.toml#l7) for a concise explanation of why this is useful. For us in practice this means that if I were to run all the tests (`cargo nextest r --workspace`) and then `cargo r`, all the deps from the previous cargo command will be reused. Before this PR it would rebuild many deps due to resolving different sets of features for them. For me this frequently caused long rebuilds when things "should" already be cached. To avoid manually maintaining our workspace-hack crate, we will use [cargo hakari](https://docs.rs/cargo-hakari) to update the build files when there's a necessary change. I've added a step to CI that checks whether the workspace-hack crate is up to date, and instructs you to re-run `script/update-workspace-hack` when it fails. Finally, to make sure that people can still depend on crates in our workspace without pulling in all the workspace deps, we use a `[patch]` section following [hakari's instructions](https://docs.rs/cargo-hakari/0.9.36/cargo_hakari/patch_directive/index.html) One possible followup task would be making guppy use our `rust-toolchain.toml` instead of having to duplicate that list in its config, I opened an issue for that upstream: guppy-rs/guppy#481. TODO: - [x] Fix the extension test failure - [x] Ensure the dev dependencies aren't being unified by Hakari into the main dependencies - [x] Ensure that the remote-server binary continues to not depend on LibSSL Release Notes: - N/A --------- Co-authored-by: Mikayla <mikayla@zed.dev> Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com> |
||
|
|
d6520954b6 |
chore: Bump Rust edition to 2024 (#27800)
Follow-up to https://github.com/zed-industries/zed/pull/27791 Release Notes: - N/A |
||
|
|
1ebb9032c4 |
Change license of crates/livekit_api from AGPL to GPL (#25206)
Release Notes: - N/A |
||
|
|
2cef9e5450 |
Rename livekit_server to livekit_api (#24984)
The name `livekit_server` was a bit misleading as it is not a server and gets built into both the client and server - the server code is in `collab`. Release Notes: - N/A |