Fix SSRF (Server Side Request Forgery) in Warp
SSRF in Warp-based Rust services typically manifests when user-controlled strings are passed directly into an HTTP client like reqwest. In a cloud-native environment, this is a critical vulnerability that allows attackers to exfiltrate IMDS credentials (169.254.169.254) or pivot into internal microservices. Rust's type safety won't save you from logic-level SSRF; you need explicit network-level validation.
The Vulnerable Pattern
use warp::Filter; use std::collections::HashMap;#[tokio::main] async fn main() { let proxy = warp::path(“fetch”) .and(warp::query::<HashMap<String, String>>()) .and_then(|q: HashMap<String, String>| async move { let target = q.get(“url”).ok_or_else(warp::reject::not_found)?; // VULNERABLE: Direct fetch of user-controlled URL let resp = reqwest::get(target).await.map_err(|| warp::reject::not_found())?; let body = resp.text().await.map_err(|| warp::reject::not_found())?; Ok::<_, warp::Rejection>(warp::reply::html(body)) });
warp::serve(proxy).run(([127, 0, 0, 1], 3030)).await;
}
The Secure Implementation
The secure implementation mitigates SSRF through four primary controls. 1. Protocol Whitelisting: Enforcing 'https' prevents protocol smuggling (e.g., file://, gopher://). 2. URL Parsing: Using the 'url' crate ensures the input is well-formed before processing. 3. DNS Resolution & Validation: We resolve the hostname to IP addresses before making the request. This allows us to check against RFC 1918 private address ranges and loopback addresses. 4. DNS Rebinding Protection: By validating the resolved IP and then ideally pinning the request to that IP (or re-validating), we prevent attackers from switching a safe domain to a malicious internal IP between the time of check and time of use.
use warp::Filter; use url::Url; use std::net::IpAddr;async fn is_safe_url(target: &str) -> Result<Url, ()> { let parsed = Url::parse(target).map_err(|_| ())?; if parsed.scheme() != “https” { return Err(()); }
let host = parsed.host_str().ok_or(())?; let addrs = tokio::net::lookup_host(format!("{}:443", host)).await.map_err(|_| ())?; for addr in addrs { let ip = addr.ip(); if ip.is_loopback() || ip.is_unspecified() || is_private_ip(ip) { return Err(()); } } Ok(parsed)}
fn is_private_ip(ip: IpAddr) -> bool { match ip { IpAddr::V4(v4) => v4.is_private(), IpAddr::V6(_) => true, // Simplification for example: block all IPv6 if not managed } }
// Use in Warp filter via .and_then(|q| async move { let url = is_safe_url(&q[“url”]).await?; … })
Your Warp API
might be exposed to SSRF (Server Side Request Forgery)
74% of Warp apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.
Free Tier • No Credit Card • Instant Report
Verified by Ghost Labs Security Team
This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.