HIGH xss cross site scriptingaxum

Xss Cross Site Scripting in Axum

How XSS Cross-Site Scripting Manifests in Axum

Cross-Site Scripting (XSS) in Axum applications occurs when untrusted user input is rendered in HTML without proper sanitization. Axum's macro-based routing system and extractors make it easy to build APIs, but developers must be vigilant about output encoding when serving HTML content.

The most common XSS vectors in Axum include:

  • Dynamic HTML generation: Using extractors like Query, Path, or Json to capture user input and directly embedding it in HTML templates
  • Template injection: Passing unsanitized data to template engines like Askama or Handlebars
  • JavaScript injection: Including user-controlled data in <script> tags, event handlers, or JSON responses
  • URL-based attacks: Reflected XSS through query parameters or path segments

Consider this vulnerable Axum route:

use axum::extract::Query;
use axum::response::Html;

async fn profile_page(Query(params): Query<HashMap<String, String>>) -> Html<String> {
    let username = params.get("username").unwrap_or("Guest");
    let html = format!("<h1>Welcome, {}</h1><p>Your profile</p>", username);
    Html(html)
}

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

If an attacker requests /profile?username=<script>alert(1)</script>, the script executes in victims' browsers. Axum itself doesn't provide automatic output encoding—developers must implement it manually or use safe templating.

Stored XSS can also occur when Axum APIs accept HTML content that gets persisted and later rendered. For example, a comment system API might accept HTML without sanitization:

async fn create_comment(Json(payload): Json<Comment>) -> impl Responder {
    // payload.content is stored and later rendered without sanitization
    store_comment(payload.content).await
}

#[derive(Deserialize)]
struct Comment {
    content: String,
}

The vulnerability here is accepting raw HTML from clients without validation or sanitization.

Axum-Specific Detection

Detecting XSS in Axum applications requires both static analysis and runtime scanning. Static analysis tools can identify dangerous patterns like direct string interpolation in HTML generation, but runtime scanning reveals actual vulnerabilities.

middleBrick's black-box scanning approach is particularly effective for Axum APIs. It tests unauthenticated endpoints by sending payloads that trigger XSS conditions and analyzes responses for script execution or HTML injection. The scanner checks:

  • Reflected XSS in query parameters and path segments
  • Stored XSS through API endpoints that accept HTML content
  • DOM-based XSS by examining JSON responses for executable content
  • Template injection vulnerabilities

For Axum applications, middleBrick scans endpoints like:

GET /api/profile?username=<script>alert(1)</script>
POST /api/comments { "content": "<img src=x onerror=alert(1)>" }
GET /api/data?callback=<script>alert(1)</script>

The scanner evaluates whether responses contain the injected payloads in executable contexts. For template-based Axum applications using Askama, middleBrick can analyze template files alongside runtime behavior to identify unsafe data binding.

Manual detection techniques include:

use axum::extract::Query;
use axum::response::Html;

async fn test_xss(Query(params): Query<HashMap<String, String>>) -> Html<String> {
    let test_payload = r#"<script>console.log('XSS test')</script>".to_string();
    let html = format!("<div>{}</div>", params.get("test").unwrap_or(&test_payload));
    Html(html)
}

// Test by requesting: /test?test=<img+src=x+onerror=alert(1)>

middleBrick's API security scanning integrates with CI/CD pipelines via the GitHub Action, allowing you to automatically scan Axum endpoints before deployment. The Pro plan's continuous monitoring can periodically scan your API endpoints and alert you to new XSS vulnerabilities.

Axum-Specific Remediation

Remediating XSS in Axum requires a defense-in-depth approach. The most effective strategy combines output encoding, content security policies, and input validation.

For HTML generation, avoid direct string interpolation. Instead, use Axum's response types with proper encoding:

use axum::extract::Query;
use axum::response::Html;
use html_escape::encode_str;

async fn safe_profile(Query(params): Query<HashMap<String, String>>) -> Html<String> {
    let username = params.get("username").unwrap_or("Guest");
    let safe_username = encode_str(username);
    let html = format!("<h1>Welcome, {}</h1>", safe_username);
    Html(html)
}

// Cargo.toml dependency:
// html-escape = "0.2.11"

For template-based applications using Askama, leverage the template engine's auto-escaping:

use axum::extract::Path;
use axum::response::Html;
use askama::Template;

#[derive(Template)]
#[template(path = "profile.html")]
struct ProfileTemplate {
    username: String,
}

async fn profile(Path(username): Path<String>) -> Html<String> {
    let template = ProfileTemplate { username };
    Html(template.render().unwrap())
}

// profile.html uses auto-escaping by default:
// <h1>Welcome, {{ username }}</h1>

For JSON APIs, ensure proper content-type headers and avoid JSON injection:

async fn get_user_profile(Path(id): Path<i32>) -> Json<UserProfile> {
    let profile = get_profile_from_db(id).await;
    Json(profile)
    // Axum automatically sets Content-Type: application/json
    // and handles proper JSON encoding
}

#[derive(Serialize)]
struct UserProfile {
    username: String,
    bio: String,
}

// Always validate and sanitize input data before processing

Implement Content Security Policy headers to mitigate XSS impact:

use axum::http::HeaderValue;
use axum::response::{Html, IntoResponse};

async fn csp_protected_page() -> impl IntoResponse {
    let csp = HeaderValue::from_static(
        "default-src 'self'; script-src 'self' 'nonce-random123';"
    );
    (csp, Html("<script nonce='random123'>console.log('safe')</script>".to_string()))
}

// Add middleware to set CSP headers globally
use axum::middleware::Next;
use axum::response::Response;

async fn csp_middleware(
    mut req: axum::http::Request<body::Body>,
    next: Next<body::Body>,
) -> Result<Response, axum::http::Error> {
    let mut res = next.run(req).await?;
    res.headers_mut().insert(
        "Content-Security-Policy",
        HeaderValue::from_static(
            "default-src 'self'; script-src 'self';"
        ),
    );
    Ok(res)
}

let app = Router::new()
    .route("/", get(index))
    .layer(axum::middleware::from_fn(csp_middleware));

For input validation, use libraries like validator to sanitize user input before processing:

use validator::validate_email;

async fn register_user(Json(payload): Json<RegisterRequest>) -> impl Responder {
    if !validate_email(&payload.email) {
        return Json(json!({ "error": "Invalid email format" }));
    }
    
    // Sanitize other fields
    let safe_username = sanitize_html(&payload.username);
    create_user(safe_username, payload.email).await
}

#[derive(Deserialize)]
struct RegisterRequest {
    username: String,
    email: String,
}

middleBrick's Pro plan includes continuous monitoring that can scan your Axum API endpoints on a schedule, alerting you to XSS vulnerabilities before they reach production. The GitHub Action integration allows you to fail CI builds if XSS risks are detected in your API endpoints.

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

How does middleBrick detect XSS vulnerabilities in Axum applications?
middleBrick performs black-box scanning of your Axum API endpoints by sending test payloads containing XSS vectors to your URLs. It analyzes responses for reflected XSS, stored XSS, and DOM-based XSS patterns. The scanner checks query parameters, path segments, and JSON bodies for script execution or HTML injection. For template-based Axum applications, middleBrick can analyze template files alongside runtime scanning to identify unsafe data binding patterns.
Can middleBrick scan my Axum API during development?
Yes, middleBrick offers multiple scanning options for Axum APIs. The free plan allows 3 scans per month for testing. The CLI tool lets you scan locally with middlebrick scan http://localhost:3000. The GitHub Action integrates with your CI/CD pipeline to scan staging APIs before deployment. The Pro plan includes continuous monitoring that can scan your Axum endpoints on a configurable schedule and alert you to new XSS vulnerabilities.