v0.14 is out: a mobile auth pack for Swift/iOS and Android, catching insecure token storage, cleartext traffic, and OAuth in embedded WebViews. Read more →
HIGH AI PREVALENCE: HIGH auth.rust.flow.ssrf

Untrusted request input flows into the URL of an outbound HTTP request.

Why AI tools produce this: AI coding tools generate this anti-pattern by default, it appears in a large share of AI-written auth code.

Why this matters

Because the destination is attacker-controlled, this is a Server-Side Request Forgery (CWE-918): an attacker can point the request at internal services behind your firewall, or at the cloud metadata endpoint (http://169.254.169.254/...) to steal IAM/instance credentials and pivot deeper into your infrastructure.

Never pass a request-derived String (an axum/actix handler parameter, or a value taken from request input) straight into reqwest::get(...) or a Client::get(...) / Client::post(...).send(). Validate the destination host against an explicit allow-list (parse the URL and check the resolved host/scheme, rejecting private/loopback/link-local ranges) before issuing the request.

VULNERABLE
vulnerable.rs
use axum::extract::{Path, Query};
use std::collections::HashMap;

// Inline: a handler `String` parameter flows straight into reqwest::get.
async fn fetch(url: String) -> String {
    // ruleid: auth.rust.flow.ssrf
    reqwest::get(url).await.unwrap().text().await.unwrap()
}

// Indirection: the parameter is assigned to a local, then requested via a
// client. Taint tracks through the binding.
async fn proxy(target: String, client: reqwest::Client) -> String {
    let dest = target;
    // ruleid: auth.rust.flow.ssrf
    client.get(dest).send().await.unwrap().text().await.unwrap()
}

// POST against a request-derived URL.
async fn relay(endpoint: String, client: reqwest::Client) {
    // ruleid: auth.rust.flow.ssrf
    let _ = client.post(endpoint).send().await;
}

// axum Query extractor destructured to a struct, the inner field flows out.
async fn from_query(Query(params): Query<HashMap<String, String>>) -> String {
    let url = params.get("url").cloned().unwrap_or_default();
    // ruleid: auth.rust.flow.ssrf
    reqwest::get(url).await.unwrap().text().await.unwrap()
}

// axum Path extractor parameter into a blocking client request.
async fn from_path(Path(host): Path<String>, client: reqwest::Client) {
    // ruleid: auth.rust.flow.ssrf
    let _ = client.head(host).send().await;
}
SAFE
safe.rs
// Outbound HTTP requests that are NOT SSRF — must produce zero findings.

fn is_allowed_url(url: &str) -> bool {
    url.starts_with("https://api.internal.example.com/")
}

const ALLOWED_URLS: [&str; 1] = ["https://api.internal.example.com/health"];

// Safe: a constant, attacker-uncontrolled target (a local, not a parameter).
async fn fetch_constant(client: reqwest::Client) -> String {
    let url = "https://api.internal.example.com/health".to_string();
    // ok: auth.rust.flow.ssrf
    client.get(url).send().await.unwrap().text().await.unwrap()
}

// Safe: the parameter is only requested inside an allow-list host-validation
// guard, which clears the taint.
async fn fetch_validated(target: String, client: reqwest::Client) -> String {
    if is_allowed_url(&target) {
        // ok: auth.rust.flow.ssrf
        return client.get(target).send().await.unwrap().text().await.unwrap();
    }
    "rejected".to_string()
}

// Safe: explicit allow-list membership guard on the exact value used.
async fn fetch_guarded(endpoint: String, client: reqwest::Client) -> String {
    if ALLOWED_URLS.contains(&endpoint.as_str()) {
        // ok: auth.rust.flow.ssrf
        return client.get(endpoint).send().await.unwrap().text().await.unwrap();
    }
    "rejected".to_string()
}

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.

// oauthlint-disable-next-line auth.rust.flow.ssrf -- <reason>

References

https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html ↗https://cwe.mitre.org/data/definitions/918.html ↗