Why AI tools produce this: AI coding tools produce this regularly, typically when prompted for a shortcut or a quick fix.
Why this matters
A static state provides ZERO CSRF protection: the whole point is an unguessable, per-request value that you store and then compare on the callback. A literal that ships in your source is known to everyone and identical on every request, so an attacker can forge a matching callback.
Use CsrfToken::new_random (the oauth2 crate's CSPRNG-backed generator), pass it to authorize_url, persist it in the session, and verify it when the provider redirects back.
VULNERABLE
vulnerable.rs
use oauth2::basic::BasicClient;use oauth2::CsrfToken;// Hardcoded state via .to_string() — constant on every request.fn authorize_static(client: &BasicClient) { // ruleid: auth.rust.oauth.static-state let _ = client.authorize_url(|| CsrfToken::new("static-state-123".to_string()));}// Hardcoded state via String::from.fn authorize_static_from(client: &BasicClient) { // ruleid: auth.rust.oauth.static-state let _ = client.authorize_url(|| CsrfToken::new(String::from("constant")));}// Hardcoded state via .into().fn authorize_static_into(client: &BasicClient) { // ruleid: auth.rust.oauth.static-state let _ = client.authorize_url(|| CsrfToken::new("fixed".into()));}fn main() {}
SAFE
safe.rs
use oauth2::basic::BasicClient;use oauth2::CsrfToken;// Safe: a fresh per-request CSPRNG-backed state.fn authorize_random(client: &BasicClient) { // ok: auth.rust.oauth.static-state let _ = client.authorize_url(CsrfToken::new_random);}// helper that derives a state value at runtimefn derive_state(session_id: &str) -> String { format!("{}-{}", session_id, "nonce")}// Safe trap: the argument is a function call (with its own string literal// inside), not a literal state — the precise literal-only patterns must not// match it.fn authorize_derived(client: &BasicClient, session_id: &str) { let state = derive_state(session_id); // ok: auth.rust.oauth.static-state let _ = client.authorize_url(|| CsrfToken::new(state.clone()));}fn main() {}
Suppressing this rule
If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.