HIGH graphql introspectionaxumapi keys

Graphql Introspection in Axum with Api Keys

Graphql Introspection in Axum with Api Keys — how this specific combination creates or exposes the vulnerability

GraphQL introspection is a feature that allows clients to query the schema of a GraphQL service, including types, queries, and mutations. When enabled in production, it can expose implementation details that assist attackers in crafting injection or privilege escalation attacks. In an Axum-based Rust service, introspection is typically controlled by the GraphQL library configuration. If introspection is left enabled and the endpoint is protected only by API keys, the exposure surface changes in a meaningful way.

API keys are a common authentication mechanism where a secret string is passed in headers or query parameters to identify the caller. In Axum, this is often implemented via middleware that checks for a key before allowing the request to proceed. When GraphQL introspection is allowed alongside API key protection, an attacker who does not yet have a valid key might still be able to perform introspection if the middleware applies authentication too late in the request pipeline. For example, if the GraphQL handler is invoked before the key validation middleware runs, or if the introspection resolver is not explicitly guarded, the schema can be leaked without proper authorization checks.

Consider a typical Axum setup where routes are defined and middleware is applied. If the GraphQL route uses a wrapper that does not correctly enforce authentication before invoking the GraphQL introspection resolver, the introspection query can succeed regardless of the key’s validity or presence. This effectively turns the API key into a weak gatekeeper: the key may be required for normal operations, but introspection bypasses its intent. Attackers can use introspection to discover query names, filter patterns, and relationships, which can then be used to probe for IDOR, BOLA, or other logic flaws.

Furthermore, if the API key is passed in a predictable header or query parameter and introspection is enabled, automated scanners can correlate the presence of a valid key with schema exposure. This can lead to a clearer picture of how authorization is applied across different fields and types in the schema, increasing the risk of privilege escalation or data exposure. In a black-box scan, an unauthenticated introspection query against an Axum endpoint with API key protection may still succeed if the middleware configuration does not short-circuit the GraphQL execution on missing or invalid keys.

To detect this using middleBrick, a scan would include checks for Authentication and BOLA/IDOR alongside GraphQL-specific probes. The scanner validates whether introspection can be executed without valid credentials and whether the API key enforcement is consistently applied across all GraphQL operations. Remediation guidance focuses on ensuring introspection is disabled in production and that authentication is enforced before any GraphQL resolver is invoked.

Api Keys-Specific Remediation in Axum — concrete code fixes

Securing GraphQL introspection in Axum with API keys requires precise control over middleware ordering and explicit disabling of introspection in production. Below are concrete, working examples that demonstrate how to implement this correctly.

Example 1: Disabling introspection via schema building

When creating your GraphQL schema, disable introspection by setting introspection_limit and ensuring the schema is built without introspection support. This prevents introspection regardless of route configuration.

use async_graphql::{Schema, EmptySubscription, Object};
use async_graphql::http::{GraphiQLSource, GraphQLRequest};
use async_graphql::parser::types::Schema as GraphQLSchema;

struct Query;
#[Object]
impl Query {
    async fn hello(&self) -> &str {
        "world"
    }
}

let schema = Schema::build(Query, EmptySubscription, EmptySubscription)
    .introspection_limit(async_graphql::http::IntrospectionLimit::Disable)
    .finish();

Example 2: Axum middleware enforcing API keys before GraphQL handler

This example shows an Axum route where API key validation occurs before the GraphQL handler is invoked. The middleware returns 401 if the key is missing or invalid, ensuring introspection cannot bypass the check.

use axum::{Router, routing::post, extract::Request, http::StatusCode};
use axum::middleware::Next;
use std::sync::Arc;

async fn api_key_middleware(
    request: Request,
    next: Next,
) -> Result {
    let valid = validate_api_key(request.headers());
    if !valid {
        return Err((StatusCode::UNAUTHORIZED, "Invalid API key".to_string()));
    }
    Ok(next.run(request).await)
}

fn validate_api_key(headers: &axum::http::HeaderMap) -> bool {
    const EXPECTED: &str = "secret_key_123";
    headers.get("X-API-Key")
        .and_then(|v| v.to_str().ok())
        .map(|s| s == EXPECTED)
        .unwrap_or(false)
}

let app = Router::new()
    .route("/graphql", post(graphql_handler))
    .layer(axum::middleware::from_fn(api_key_middleware));

Example 3: Explicitly rejecting introspection in the GraphQL handler

Even with schema-level disabling, you can add runtime checks inside your handler to reject introspection queries when API keys are used. This provides defense-in-depth.

use async_graphql::Request;

async fn graphql_handler(
    axum::extract::State(schema): axum::extract::State>>,
    axum::extract::Header(axum::http::header::AUTHORIZATION): Option,
    request: Request,
) -> impl IntoResponse {
    if request.is_introspection() {
        return Err("Introspection is disabled") as &str;
    }
    let response = schema.execute(request).await;
    // return response
}

These examples ensure that API keys are validated early and that introspection is disabled or explicitly rejected. middleBrick scans can verify that these protections are present by checking for Authentication and GraphQL-specific findings.

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 API keys alone prevent GraphQL introspection leaks in Axum?
No. API keys must be enforced before the GraphQL handler runs; otherwise introspection may bypass the check. Disable introspection in production and validate keys in middleware.
How does middleBrick detect GraphQL introspection issues in Axum services?
middleBrick runs authentication and GraphQL-specific checks, attempting introspection without credentials and verifying whether API key enforcement occurs before schema queries.