Data Exposure in Axum with Api Keys
Data Exposure in Axum with Api Keys
Data exposure in Axum applications often occurs when API keys are handled without adequate safeguards, leading to their unintended leakage in logs, error messages, or client‑side artifacts. Axum, a web framework for Rust, does not inherently expose keys, but common patterns in route handling, request extensions, and logging can inadvertently surface them.
Consider an Axum handler that receives an API key via an HTTP header and forwards it to downstream services. If the key is stored in a request extension and later serialized into debug output or trace logs, it may be exposed to anyone who can view those logs. For example, using the tracing crate to log the entire request extensions map can print the key in plaintext if the developer is not careful about what is recorded.
Another exposure path is error handling. When an Axum handler panics or returns an error that includes request metadata, frameworks like axum::debug_handler or custom error responses might echo back headers or extension values. Inadequate sanitization of error payloads can leak API keys to clients or monitoring systems. This is especially risky when responses include detailed trace information in development mode but are mistakenly left verbose in production.
A third scenario involves serialization and caching. If an API key is placed into a structure that is later cached or stored—intentionally or unintentionally—and that structure is serialized (for example, with serde) into logs, metrics, or external storage, the key can persist beyond its intended lifecycle. Combined with insufficient access controls on logs or monitoring dashboards, this creates a data exposure vector where keys are readable by unauthorized users or systems.
In each case, the root cause is not Axum itself but the surrounding application logic: how keys are passed, logged, serialized, and surfaced in errors. Because middleBrick tests unauthenticated attack surfaces, it can detect endpoints that reflect API keys in responses or logs, flagging them as data exposure findings with severity and remediation guidance.
Api Keys-Specific Remediation in Axum
To prevent data exposure of API keys in Axum, ensure keys are handled as sensitive values that are never logged, echoed in errors, or serialized unnecessarily. Use dedicated secure storage for keys, limit their scope to the minimal required context, and sanitize all outputs that might include request metadata.
Below are concrete Axum code examples that demonstrate unsafe patterns and their secure alternatives.
Unsafe pattern: Logging headers including API keys
use axum::{routing::get, Router, http::HeaderMap};
use tracing::info;
async fn handler(headers: HeaderMap) -> String {
// UNSAFE: logging headers can expose API keys
info!(?headers, "Request received");
"ok".to_string()
}
let app = Router::new().route("/", get(handler));
Remediation: redact sensitive headers before logging.
use axum::{routing::get, Router, http::HeaderMap};
use tracing::info;
fn redact_api_key(headers: &HeaderMap) -> impl std::fmt::Debug + '_ {
struct RedactedHeaders<'a>(&'a HeaderMap);
impl<'a> std::fmt::Debug for RedactedHeaders<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut dbg = f.debug_map();
for (key, value) in self.0.iter() {
let key_str = key.as_str();
let val_str = if key_str.eq_ignore_ascii_case("authorization") || key_str.eq_ignore_ascii_case("x-api-key") {
"[REDACTED]"
} else {
std::str::from_utf8(value).unwrap_or("")
};
dbg.entry(&key_str, &val_str);
}
dbg.finish()
}
}
RedactedHeaders(headers)
}
async fn handler(headers: HeaderMap) -> String {
info!(headers = ?redact_api_key(&headers), "Request received");
"ok".to_string()
}
let app = Router::new().route("/", get(handler));
Unsafe pattern: Echoing headers in error responses
use axum::{routing::post, Json, http::StatusCode};
use serde::Deserialize;
#[derive(Deserialize)]
struct Payload { api_key: String }
async fn handler(Json(payload): Json) -> Result {
// UNSAFE: returning the key in an error response
if payload.api_key.is_empty() {
return Err((StatusCode::BAD_REQUEST, format!("Invalid API key: {}", payload.api_key)));
}
Ok("success".to_string())
}
let app = Router::new().route("/check", post(handler));
Remediation: return generic error messages and avoid including key values.
use axum::{routing::post, Json, http::StatusCode};
use serde::Deserialize;
#[derive(Deserialize)]
struct Payload { api_key: String }
async fn handler(Json(payload): Json) -> Result {
if payload.api_key.is_empty() {
// Safe: do not echo the key value
return Err((StatusCode::BAD_REQUEST, "Invalid API key".to_string()));
}
// Process the key securely without exposing it
Ok("success".to_string())
}
let app = Router::new().route("/check", post(handler));
Best practice: Use request extensions for scoped key access
use axum::{routing::get, Router, extract::Extension};
use std::sync::Arc;
struct Config { api_key: String }
async fn handler(Extension(cfg): Extension>) -> String {
// Use cfg.api_key internally without logging or exposing it
if cfg.api_key.is_empty() {
return "forbidden".to_string();
}
"authorized".to_string()
}
let config = Arc::new(Config { api_key: "super-secret".to_string() });
let app = Router::new()
.layer(Extension(config))
.route("/", get(handler));
By keeping API keys in controlled extension state and avoiding their serialization or inclusion in logs and error messages, you significantly reduce the risk of data exposure in Axum services. middleBrick can identify endpoints that reflect sensitive values by scanning unauthenticated attack surfaces and will provide prioritized findings with severity levels and remediation steps.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |