Repository navigation
Description
Summary: crates/auth/src/oauth.rs::verify_state returns true when both received and expected are the empty string. A caller that maps "no stored state" to an empty string on both sides (instead of rejecting absent state before comparing) would pass CSRF-state verification incorrectly. I verified this is not currently reachable in production: the live OAuth callback route (crates/api/src/routes/auth.rs::handle_callback / callback_provider) never calls verify_state at all — it uses a Redis-backed GETDEL (take_oauth_flow) that atomically reads and erases the pending-flow record, and explicitly rejects with ApiError::BadRequest via .ok_or_else(...) when nothing is found, before any string comparison would happen. verify_state itself appears to be unused outside its own test module today.
Severity: S4 — latent/internal footgun. Not exploitable via any current production code path; the risk is a future caller (a refactor of the callback route, or a new integration reusing this helper) reintroducing the pattern this function is meant to guard against. Already pinned by a warning-commented test (verify_state_edge_cases, crates/auth/src/oauth.rs:263-273) so the behavior won't silently regress unnoticed, but the function itself still returns the wrong answer for empty/empty.
Environment:
- Deploy: any (pure function, not currently wired into a live route)
- Commit: 6411ddb
Repro steps:
- Call
ogrenotes_auth::oauth::verify_state("", ""). - Observe it returns
true.
Expected: Empty-vs-empty should not be treated as a valid state match — an absent/empty stored state should never successfully "verify" against an absent/empty received state; the function should reject this case (or the call site must reject it first, and that requirement should be made structurally unavoidable rather than relying on caller discipline).
Observed: verify_state("", "") returns true, per the existing test at crates/auth/src/oauth.rs:273, which pins this with a warning comment (line 272) rather than asserting the "safe" behavior.
Evidence:
- Code:
crates/auth/src/oauth.rs:71(pub fn verify_state) - Test (pins current behavior with a warning):
crates/auth/src/oauth.rs:263-273 - Confirmed non-reachability:
grep -rn "verify_state" crates/api/shows no call sites outsidecrates/auth/src/oauth.rs's own module; the live callback path iscrates/api/src/routes/auth.rs:534-560(handle_callback), which usesstate.redis_session.take_oauth_flow(¶ms.state)and rejectsOk(None)before any comparison.
Suspected area: crates/auth/src/oauth.rs::verify_state — add an explicit rejection for empty/empty (or empty-either-side) inputs so the function is safe by construction rather than relying on every future caller to pre-check for absent state.
Activity
fix(mermaid): gitGraph label anchoring + xychart series palette (gall…