Ssrf in Actix with Bearer Tokens
Ssrf in Actix with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Server-Side Request Forgery (SSRF) in Actix web applications becomes particularly high-risk when Bearer Tokens are involved. In this combination, an attacker can leverage SSRF to make the server perform HTTP requests on its behalf, automatically including the Bearer Token in outbound headers. Because the token is often sourced from incoming request headers, middleware, or configuration, the server may propagate it to internal or external endpoints without validation or isolation.
For example, if an Actix handler forwards a user-supplied URL to an internal metadata service (e.g., http://169.254.169.254 on cloud providers) and attaches the Bearer Token from the Authorization header, the SSRF enables the token to reach sensitive internal APIs that are not exposed publicly. This can lead to overprivileged actions such as reading instance metadata, invoking internal microservices, or accessing cloud orchestration endpoints. The vulnerability is not in Bearer Tokens themselves, but in the application’s trust of untrusted input combined with automatic credential propagation.
An Actix route that directly uses a user-provided URL and forwards the Authorization header without strict allowlisting is susceptible. Consider a handler that accepts a URL query parameter and uses it with an HTTP client while copying the incoming Authorization header. If the endpoint behind the user-supplied URL is controllable or internally addressable, the SSRF becomes effective, and the Bearer Token may grant unintended access. This pattern is common in integrations that proxy requests or fetch remote resources on behalf of clients.
In a black-box scan by middleBrick, such flows are detected under the SSRF and Unsafe Consumption checks. The scanner tests whether the API reflects or follows user-controlled URLs and whether outbound requests include credentials like Bearer Tokens. Findings include risk of token exfiltration from internal services, potential lateral movement, and privilege escalation if the token has elevated scopes. Remediation guidance emphasizes input validation, network-level restrictions, and minimizing the scope of tokens passed to downstream calls.
Bearer Tokens-Specific Remediation in Actix — concrete code fixes
To mitigate SSRF when using Bearer Tokens in Actix, ensure that user-controlled URLs are not used to make outbound authenticated requests. Instead, use allowlists, remove or sanitize the Authorization header for proxied calls, and apply network segmentation so that sensitive internal endpoints are not reachable from user input.
Below are concrete code examples for Actix handlers that demonstrate secure patterns.
Example 1: Rejecting non-allowlisted destinations
Validate the target host against an allowlist and reject private IP ranges and internal domains before making any HTTP call.
use actix_web::{web, HttpResponse, Result};
use reqwest::Client;
use url::Url;
async fn fetch_external(data: web::Json) -> Result {
let target = Url::parse(&data.url).map_err(|_| HttpResponse::BadRequest().finish())?;
// Allowlist approach: only permit known safe hosts
let allowed_hosts = ["api.github.com", "api.example.com"];
if !allowed_hosts.contains(&target.host_str().unwrap_or("")) {
return Ok(HttpResponse::Forbidden().body("destination not allowed"));
}
// Block private/reserved destinations
if let Some(host) = target.host_str() {
if host == "169.254.169.254" || host.ends_with(".internal") {
return Ok(HttpResponse::Forbidden().body("internal destination not allowed"));
}
}
let client = Client::new();
let response = client
.get(target.as_str())
.bearer_auth(&data.token) // token explicitly provided, not forwarded from incoming Authorization
.send()
.await
.map_err(|_| HttpResponse::InternalServerError().finish())?;
let body = response.text().await.map_err(|_| HttpResponse::InternalServerError().finish())?;
Ok(HttpResponse::Ok().body(body))
}
#[derive(serde::Deserialize)]
struct FetchRequest {
url: String,
token: String,
}
Example 2: Stripping incoming Authorization when proxying
If you must proxy to a user-supplied URL, do not forward the incoming Authorization header. Instead, use a service-specific token or no token if the destination does not require authentication.
use actix_web::{web, Error, HttpResponse};
use reqwest::Client;
async fn proxy_without_auth(body: web::Json) -> Result {
let client = Client::new();
// Build request without copying Authorization header from the incoming request
let mut req = client.get(&body.target_url);
// Only add a token if the destination is explicitly trusted and requires it
if body.use_service_token {
req = req.bearer_auth(&body.service_token);
}
let resp = req.send().await.map_err(|_| Error::from(HttpResponse::BadGateway().finish()))?;
let text = resp.text().await.map_err(|_| Error::from(HttpResponse::BadGateway().finish()))?;
Ok(HttpResponse::Ok().body(text))
}
#[derive(serde::Deserialize)]
struct ProxyRequest {
target_url: String,
// Do not include incoming_authorization: &str
use_service_token: bool,
service_token: String,
}
Additional hardening steps include placing outbound calls behind a controlled proxy or gateway with egress filtering, using short-lived tokens with minimal scopes, and monitoring for unusual destinations in logs. middleBrick’s scans validate that user-controlled URLs do not lead to authenticated calls to internal endpoints and highlight missing allowlists.
Related CWEs: ssrf
| CWE ID | Name | Severity |
|---|---|---|
| CWE-918 | Server-Side Request Forgery (SSRF) | CRITICAL |
| CWE-441 | Unintended Proxy or Intermediary (Confused Deputy) | HIGH |