Path Traversal in Axum with Api Keys
Path Traversal in Axum with Api Keys — how this specific combination creates or exposes the vulnerability
Path Traversal occurs when user-controlled input used in file system operations is not properly sanitized, allowing an attacker to navigate outside the intended directory. In an Axum application that uses Api Keys for authorization, the risk emerges when an endpoint accepts a filename or path parameter and combines it with a base directory without validation. Even when an Api Key confirms a caller is authenticated, the handler may still construct unsafe paths such as format!("/data/{}", user_input). If user_input contains sequences like ../, an attacker can traverse parent directories and access or overwrite files outside the service’s intended scope.
Consider an Axum route that retrieves user documents by ID and file name, where the route also requires a valid Api Key in a header. The handler might concatenate the user-supplied filename directly with a storage root path. Because the Api Key check passes, the request is considered authorized, but the file resolution is unchecked. This means an authenticated caller can request ../../../etc/passwd to read system files. In a black-box scan, middleBrick tests unauthenticated attack surfaces; if an endpoint inadvertently exposes path construction logic or error messages that reveal filesystem layout, middleBrick can detect insecure handling. The combination of per-route authorization (Api Keys) and unchecked path parameters amplifies the impact: a compromised or rogue client with a valid key can leverage traversal to read sensitive files or, if the application has write capabilities, to modify or delete files.
Additionally, Axum extractors such as Query or Path can inadvertently pass raw values into filesystem operations. For example, using std::fs::read with a concatenated path derived from extractor data without canonicalization or prefix enforcement creates a straightforward traversal vector. The presence of Api Keys does not mitigate this; it only identifies which principal is making the request. Therefore, security reviews must examine how each authorized route resolves user input into filesystem paths and ensure that validation occurs regardless of authorization status.
Api Keys-Specific Remediation in Axum — concrete code fixes
To remediate Path Traversal in Axum when using Api Keys, ensure that all user-controlled path components are validated, sanitized, and resolved against a strict base directory. Do not rely on authorization checks alone to prevent unsafe file access. Use canonicalization and prefix checks to guarantee that resolved paths remain within allowed directories. Below are concrete, working examples for Axum handlers that incorporate Api Key validation and safe path handling.
Example 1: Safe path resolution with Api Key authorization
use axum::{routing::get, Router, extract::State, http::HeaderMap};
use std::path::{Path, PathBuf};
use std::sync::Arc;
struct AppState {
api_keys: Vec,
base_dir: PathBuf,
}
async fn get_document(
State(state): State>,
headers: HeaderMap,
axum::extract::Path(filename): axum::extract::Path(String),
) -> Result {
// 1) Authenticate via Api Key
let api_key = headers.get("X-API-Key")
.and_tk(|h| h.to_str().ok())
.ok_or((axum::http::StatusCode::UNAUTHORIZED, "Missing Api Key".to_string()))?;
if !state.api_keys.contains(&api_key.to_string()) {
return Err((axum::http::StatusCode::FORBIDDEN, "Invalid Api Key".to_string()));
}
// 2) Validate and sanitize filename
if filename.contains("..") || filename.contains('/') {
return Err((axum::http::StatusCode::BAD_REQUEST, "Invalid filename".to_string()));
}
// 3) Construct safe path
let mut path = state.base_dir.clone();
path.push(filename);
// 4) Ensure the resolved path is within base_dir
let canonical_base = state.base_dir.canonicalize().map_err(|_| (axum::http::StatusCode::INTERNAL_SERVER_ERROR, "Server error".to_string()))?;
let canonical_path = path.canonicalize().map_err(|_| (axum::http::StatusCode::NOT_FOUND, "File not found".to_string()))?;
if !canonical_path.starts_with(&canonical_base) {
return Err((axum::http::StatusCode::FORBIDDEN, "Path traversal attempt".to_string()));
}
// 5) Read file safely
use std::fs;
let content = fs::read_to_string(canonical_path).map_err(|_| (axum::http::StatusCode::INTERNAL_SERVER_ERROR, "Read error".to_string()))?;
Ok(content)
}
fn main() {
let state = Arc::new(AppState {
api_keys: vec!["s3cr3t_k3y".to_string()],
base_dir: PathBuf::from("/var/app/uploads"),
});
let app = Router::new()
.route("/documents/:filename", get(get_document))
.with_state(state);
// axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
}
Example 2: Reject traversal attempts early
use axum::extract::Path;
fn is_safe_path(input: &str) -> bool {
let cleaned = input.trim().trim_matches('/');
// Reject any path that attempts directory traversal
if cleaned.contains("..") || cleaned.starts_with('/') {
return false;
}
// Ensure no path separators remain
!cleaned.contains(std::path::MAIN_SEPARATOR)
}
async fn download(
Path(filename): Path,
) -> Result {
if !is_safe_path(&filename) {
return Err((axum::http::StatusCode::BAD_REQUEST, "Invalid path".to_string()));
}
// Proceed with safe filename usage
Ok(format!("Serving: {}", filename))
}
These examples show how Api Key checks and strict path validation work together without conflating responsibilities. middleBrick can help identify endpoints where path construction occurs alongside authorization by scanning for insecure patterns and error disclosures. By combining runtime scans with code reviews focused on path resolution, you reduce the likelihood that authenticated routes become vectors for unauthorized file access.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |
Frequently Asked Questions
Does using Api Keys alone prevent Path Traversal in Axum?
What patterns should I reject to avoid traversal in Axum handlers?
.. or path separators, and always resolve user-supplied names against a strict base directory with canonicalization checks to ensure the final path remains within the intended location.