Why AI tools produce this: AI coding tools produce this regularly, typically when prompted for a shortcut or a quick fix.
Why this matters
Authorization codes, client_secret, access/refresh tokens, and the code_verifier then travel unencrypted. A network attacker can read or rewrite them and take over the flow.
RFC 6749 §3.1 / §10.9 require TLS for the authorization and token endpoints. Use https:// for every authorize, token, and userinfo URL (including the oauth2 crate's AuthUrl / TokenUrl). http://localhost is fine for local development and is not flagged.
VULNERABLE
vulnerable.rs
use oauth2::{AuthUrl, TokenUrl};// oauth2 crate endpoints configured over cleartext http://.fn insecure_endpoints() -> (AuthUrl, TokenUrl) { // ruleid: auth.rust.oauth.insecure-token-endpoint let auth = AuthUrl::new("http://issuer.example.com/oauth/authorize".to_string()).unwrap(); // ruleid: auth.rust.oauth.insecure-token-endpoint let token = TokenUrl::new("http://issuer.example.com/oauth/token".to_string()).unwrap(); (auth, token)}// A hand-built authorize URL over http with OAuth query markers.fn insecure_authorize_url() -> &'static str { // ruleid: auth.rust.oauth.insecure-token-endpoint "http://issuer.example.com/auth?response_type=code&client_id=app"}fn main() {}
SAFE
safe.rs
use oauth2::{AuthUrl, TokenUrl};// Safe: every OAuth endpoint uses https://.fn secure_endpoints() -> (AuthUrl, TokenUrl) { // ok: auth.rust.oauth.insecure-token-endpoint let auth = AuthUrl::new("https://issuer.example.com/oauth/authorize".to_string()).unwrap(); let token = TokenUrl::new("https://issuer.example.com/oauth/token".to_string()).unwrap(); (auth, token)}// Safe: localhost over http is allowed for local development.fn local_dev_token() -> TokenUrl { // ok: auth.rust.oauth.insecure-token-endpoint TokenUrl::new("http://localhost:8080/oauth/token".to_string()).unwrap()}// Safe trap: a generic cleartext http URL with no OAuth marker must not fire.fn health_url() -> &'static str { // ok: auth.rust.oauth.insecure-token-endpoint "http://issuer.example.com/healthz"}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.