MEDIUM open redirectaxum

Open Redirect in Axum

How Open Redirect Manifests in Axum

Open Redirect vulnerabilities in Axum applications typically occur when user-controlled input is used to construct redirect URLs without proper validation. In Axum, this commonly appears in route handlers that accept query parameters for redirection, such as OAuth callbacks, login flows, or navigation helpers.

use axum::http::Uri;
use axum::response::{IntoResponse, Redirect};
use axum::routing::get;
use axum::Router;

async fn login(
    Query(params): Query,
) -> impl IntoResponse {
    // Vulnerable: user-controlled 'redirect_to' parameter
    // is used directly without validation
    Redirect::to(params.redirect_to.clone())
}

#[derive(serde::Deserialize)]
struct LoginParams {
    redirect_to: String,
}

let app = Router::new()
    .route("/login", get(login));

This pattern is dangerous because an attacker can craft a URL like /login?redirect_to=https://evil.com, causing the application to redirect users to a malicious site. The vulnerability becomes more severe when combined with authentication flows, where an attacker could redirect users after successful login to a phishing site that captures credentials.

Another common manifestation in Axum involves using Uri::from_parts or Uri::builder with user input:

use axum::http::Uri;
use axum::response::Redirect;

async fn callback(
    Path(user_id): Path,
    Query(params): Query,
) -> impl IntoResponse {
    let redirect_uri = Uri::from_parts(params.redirect_uri.clone())
        .expect("valid URI");
    
    // Vulnerable: no validation of redirect_uri
    Redirect::to(redirect_uri)
}

#[derive(serde::Deserialize)]
struct CallbackParams {
    redirect_uri: String,
}

The danger here is that Uri::from_parts will accept any valid URI scheme, including javascript:, data:, or file: schemes, which can lead to XSS or other attacks beyond simple HTTP redirects.

Axum-Specific Detection

Detecting Open Redirect vulnerabilities in Axum applications requires examining route handlers that construct redirect responses from user input. The middleBrick API security scanner can automatically identify these issues by analyzing your Axum application's endpoints.

When middleBrick scans an Axum application, it looks for patterns where:

  • Query parameters are used to construct redirect URLs without validation
  • Path parameters containing URL-like strings are used in redirect responses
  • Request body parameters are reflected in redirect locations
  • Header values (like Referer) are used to construct redirects

For example, middleBrick would flag the following vulnerable Axum route:

async fn oauth_callback(
    Query(params): Query<OauthParams>,
) -> impl IntoResponse {
    // middleBrick flags this as vulnerable
    Redirect::to(params.state.clone())
}

#[derive(serde::Deserialize)]
struct OauthParams {
    state: String,
}

The scanner tests these endpoints by sending requests with various URI schemes and external domains, then analyzing the responses to detect whether the application redirects to arbitrary locations. middleBrick's LLM/AI security module also checks for prompt injection vulnerabilities that could be chained with Open Redirect in AI-powered applications.

For local development and CI/CD integration, you can use the middleBrick CLI to scan your Axum application:

npx middlebrick scan http://localhost:3000/login

This command will analyze your running Axum server and provide a security score with specific findings about Open Redirect vulnerabilities and other API security issues.

Axum-Specific Remediation

Securing Axum applications against Open Redirect requires validating redirect targets against a whitelist of allowed destinations. Axum's type system and middleware can help enforce these security controls.

The most secure approach is to use an enum of allowed redirect targets:

use axum::http::Uri;
use axum::response::{IntoResponse, Redirect};
use axum::routing::get;
use axum::Router;

#[derive(Clone, PartialEq)]
enum AllowedRedirect {
    Home,
    Dashboard,
    Profile,
}

impl AllowedRedirect {
    fn to_uri(&self) -> Uri {
        match self {
            AllowedRedirect::Home => Uri::from_static("/"),
            AllowedRedirect::Dashboard => Uri::from_static("/dashboard"),
            AllowedRedirect::Profile => Uri::from_static("/profile"),
        }
    }
}

async fn login(
    Query(params): Query<LoginParams>,
) -> impl IntoResponse {
    let redirect_target = match params.redirect_to.as_str() {
        "home" => AllowedRedirect::Home,
        "dashboard" => AllowedRedirect::Dashboard,
        "profile" => AllowedRedirect::Profile,
        _ => AllowedRedirect::Home, // default to safe value
    };
    
    Redirect::to(redirect_target.to_uri())
}

#[derive(serde::Deserialize)]
struct LoginParams {
    redirect_to: String,
}

This approach eliminates the vulnerability by removing arbitrary URL construction entirely. Users can only redirect to predefined, safe locations within your application.

For cases where external redirects are necessary (like OAuth flows), implement strict validation:

use axum::http::Uri;
use axum::response::Redirect;
use axum::routing::get;
use axum::Router;

async fn oauth_callback(
    Query(params): Query<OauthParams>,
) -> Result<impl IntoResponse, StatusCode> {
    let allowed_domains = ["https://yourapp.com", "https://yourotherapp.com"];
    
    let redirect_uri = match Uri::from_str(&params.redirect_uri) {
        Ok(uri) => uri,
        Err(_) => return Err(StatusCode::BAD_REQUEST),
    };
    
    // Validate scheme and host
    if redirect_uri.scheme_str() != Some("https") {
        return Err(StatusCode::BAD_REQUEST);
    }
    
    if let Some(host) = redirect_uri.host() {
        if !allowed_domains.contains(&host) {
            return Err(StatusCode::BAD_REQUEST);
        }
    }
    
    Ok(Redirect::to(redirect_uri))
}

#[derive(serde::Deserialize)]
struct OauthParams {
    redirect_uri: String,
}

This validation ensures redirects only go to trusted domains and uses HTTPS, preventing open redirect attacks while maintaining necessary functionality.

Frequently Asked Questions

How does middleBrick detect Open Redirect vulnerabilities in Axum applications?
middleBrick scans Axum endpoints by sending requests with various URI schemes and external domains to parameters that might be used for redirects. It analyzes the responses to detect if the application redirects to arbitrary locations. The scanner tests common patterns like query parameters used in Redirect::to(), path parameters containing URLs, and header-based redirects. middleBrick provides a security score and specific findings with remediation guidance for any Open Redirect vulnerabilities detected.
Can I integrate middleBrick scanning into my Axum CI/CD pipeline?
Yes, you can use the middleBrick GitHub Action to scan your Axum application as part of your CI/CD pipeline. Add the action to your workflow to scan staging APIs before deployment. You can configure it to fail builds if the security score drops below your threshold, ensuring Open Redirect and other vulnerabilities are caught before production. The action integrates seamlessly with Axum applications and provides JSON reports you can use for compliance documentation.