HIGH cors wildcardaxumjwt tokens

Cors Wildcard in Axum with Jwt Tokens

Cors Wildcard in Axum with Jwt Tokens — how this specific combination creates or exposes the vulnerability

A CORS wildcard (Access-Control-Allow-Origin: *) combined with JWT-based authentication in an Axum service can unintentionally expose protected endpoints to any origin. This occurs when the server includes both a wildcard CORS policy and JWT validation in the same response for authenticated requests. Because the browser enforces CORS, a response that includes an Authorization header and Access-Control-Allow-Origin: * can be read by any webpage, even if the backend correctly validates the JWT. This contradicts the intent of scope-based access control, effectively making authenticated routes accessible cross-origin without origin restrictions. The risk is especially pronounced when routes accept credentials (cookies or authorization headers) while also returning a wildcard, because it allows an attacker-controlled site to make authenticated requests on behalf of a victim and potentially read the responses. This pattern can lead to privilege escalation if the endpoint exposes sensitive data or performs actions on behalf of the authenticated user. In the context of the 12 security checks, this is flagged as a CORS misconfiguration that may map to authentication bypass vectors and should be treated as a finding with severity high. Note that CORS is a browser-enforced mechanism; non-browser clients are not restricted, but the exposure still increases the attack surface for web-based attackers.

Jwt Tokens-Specific Remediation in Axum — concrete code fixes

To remediate CORS over-permissiveness while keeping JWT validation intact in Axum, restrict Access-Control-Allow-Origin to known origins and handle credentials selectively. Below are two concrete Axum examples: one insecure wildcard setup and one corrected, origin-restricted setup.

Insecure example (to avoid)

use axum::{
    routing::get,
    Router,
    http::header::{ACCESS_CONTROL_ALLOW_ORIGIN, AUTHORIZATION},
    response::Response,
};
use std::net::SocketAddr;

async fn handler_with_wildcard() -> Response {
    let cors_middleware = tower_cors::CorsLayer::new()
        .allow_origin(tower_cors::AllowOrigin::wildcard())
        .allow_headers(vec!["authorization"].into_iter().map(Into::into).collect());
    // This response exposes authenticated routes to any origin
    Router::new()
        .route("/me", get(|_: String| async { format!("Hello") }))
        .layer(cors_middleware)
        .into_response()
}

#[tokio::main]
async fn main() {
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    axum::Server::bind(&addr)
        .serve(handler_with_wildcard().into_make_service())
        .await
        .unwrap();
}

Corrected example with origin restriction and JWT validation

use axum::{
    routing::get,
    Router,
    http::header::{ACCESS_CONTROL_ALLOW_ORIGIN, AUTHORIZATION},
    response::Response,
    extract::State,
};
use std::net::SocketAddr;
use tower_cors::CorsLayer;
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation, TokenData, Header};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
struct Claims {
    sub: String,
    exp: usize,
}

async fn handler_protected(
    State(cors_config): State,
    auth_header: Option,
) -> String {
    // Validate JWT from header
    let token = match auth_header.and_then(|v| v.to_str().ok()) {
        Some(t) => t,
        None => return "Unauthorized".into(),
    };
    let validation = Validation::new(Algorithm::HS256);
    let token_data = decode::(
        token,
        &DecodingKey::from_secret("secret".as_ref()),
        &validation,
    ).map_err(|_| "Invalid token")?;
    format!("User: {}", token_data.claims.sub)
}

async fn build_router() -> Router {
    let allowed_origin = "https://trusted.example.com".parse().unwrap();
    let cors = CorsLayer::new()
        .allow_origin(allowed_origin)
        .allow_headers(vec!["authorization"].into_iter().map(Into::into).collect())
        .allow_methods(vec!["GET", "POST"].into_iter().map(Into::into).collect());

    Router::new()
        .route("/me", get(handler_protected))
        .layer(cors)
}

#[tokio::main]
async fn main() {
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    axum::Server::bind(&addr)
        .serve(build_router().into_make_service())
        .await
        .unwrap();
}

In the corrected setup, Access-Control-Allow-Origin is set to a specific trusted origin rather than a wildcard, and the JWT validation logic runs before the response is constructed. This ensures that even if a browser sends an Authorization header, the response is not readable by unauthorized origins. For continuous protection, use the Pro plan to enable continuous monitoring and fail builds automatically if risk scores exceed your threshold via the GitHub Action. The MCP Server can also be used to scan APIs directly from your AI coding assistant to catch such misconfigurations during development.

Related CWEs: dataExposure

CWE IDNameSeverity
CWE-200Exposure of Sensitive Information HIGH
CWE-209Error Information Disclosure MEDIUM
CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
CWE-312Cleartext Storage of Sensitive Information HIGH
CWE-359Exposure of Private Personal Information (PII) HIGH
CWE-522Insufficiently Protected Credentials CRITICAL
CWE-532Insertion of Sensitive Information into Log File MEDIUM
CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
CWE-540Inclusion of Sensitive Information in Source Code HIGH

Frequently Asked Questions

Can a CORS wildcard be safe if JWT validation is strict?
No. A CORS wildcard remains permissive at the browser level; even with strict JWT validation, the response can be read by any origin that the browser allows, exposing authenticated data. Origin restriction is required to prevent cross-origin leakage.
Does middleBrick detect CORS wildcard misconfigurations with JWT setups?
Yes. middleBrick scans the unauthenticated attack surface and includes CORS misconfiguration checks among its 12 parallel security checks. Findings map to frameworks such as OWASP API Top 10 and include prioritized severity and remediation guidance. You can run scans via the CLI with middlebrick scan , in CI/CD with the GitHub Action, or directly from your IDE using the MCP Server.