Log Injection in Actix with Bearer Tokens
Log Injection in Actix with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Log injection occurs when untrusted input is written directly into log entries without proper sanitization, allowing an attacker to forge log lines or inject additional records. In Actix web applications that rely on Bearer Tokens for authorization, combining token handling with insufficiently protected logging creates a specific risk surface. When a token is received via an Authorization header such as Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9, developers may log the token or parts of it for debugging without validating or masking the value. Because Bearer tokens often resemble structured strings (e.g., JWTs with dots and Base64-like characters), they can be mistakenly treated as safe identifiers, yet they remain untrusted input from the client’s perspective.
If the application directly interpolates the token into log messages—such as using info!("Authenticated token: {}", token)—an attacker who can control the token can introduce newline characters or crafted payloads. For example, a token like abc\n伪造ログ (where the attacker provides the token) can split a single log entry into multiple lines, making it harder to correlate events or detect malicious activity. Worse, if log aggregation tools parse logs by line, injected newlines can cause misalignment between timestamps, service names, and actual events, degrading observability and potentially obscuring real attacks. In distributed systems where logs are correlated by trace or request identifiers, newline injection can fragment the audit trail, complicating incident response.
The interaction between Bearer Tokens and Actix middleware further shapes the impact. Middleware that extracts and passes tokens to downstream handlers may inadvertently pass them to logging utilities without redaction. Because Actix routes can be composed of multiple extractors and guards, a token might be logged at different layers—instrumentation points, service handlers, or error handlers—increasing the number of places where unchecked logging occurs. Moreover, if token validation fails and the application logs the raw value for diagnostic purposes, it may expose whether a particular token format is considered valid, aiding reconnaissance. Real-world patterns seen in frameworks with similar request pipelines (e.g., documented behaviors around authentication filters and structured logging) show that log injection can facilitate log forging, log injection-based XSS when logs are later rendered in UIs, and disruption of log-based monitoring, aligning with common classes in the OWASP API Top 10 related to security misconfiguration and insufficient logging/monitoring.
Bearer Tokens-Specific Remediation in Actix — concrete code fixes
Remediation focuses on preventing untrusted token values from corrupting log structure and ensuring tokens are never written in full to logs. In Actix, implement structured logging with explicit field separation and redaction, and avoid interpolating raw Authorization header values. Below are concrete examples demonstrating safe practices.
Example 1: Redacting the token before logging
Instead of logging the full token, extract only the parts needed for debugging and replace the sensitive value with a fixed placeholder. Use the log::info! macro with named parameters to maintain structured output.
use actix_web::{HttpRequest, Result};
use log::info;
fn handle_request(req: HttpRequest) -> Result<()> {
if let Some(auth_header) = req.headers().get("Authorization") {
if let Ok(auth_str) = auth_header.to_str() {
// Keep a non-sensitive representation for logs
let token_fingerprint = if auth_str.starts_with("Bearer ") {
"[REDACTED_TOKEN]"
} else {
"[INVALID_AUTH_HEADER]"
};
// Structured log without raw token
info!(method = %req.method(), path = %req.path(), token = token_fingerprint);
}
}
// ... continue processing
Ok(())
}
Example 2: Using a sanitization helper to normalize input
Create a small utility that validates the format of the Bearer token (e.g., checks prefix and basic token syntax) and returns a safe representation. This prevents newline or control characters from entering logs.
fn sanitize_bearer_token(header_value: &str) -> String {
const BEARER_PREFIX: &str = "Bearer ";
if header_value.starts_with(BEARER_PREFIX) {
let token = &header_value[BEARER_PREFIX.len()..];
// Reject tokens containing newlines or carriage returns
if token.contains('\n') || token.contains('\r') {
"[INVALID_TOKEN_CONTROL_CHARS]".to_string()
} else if token.len <= 8 {
"[TOKEN_TOO_SHORT]".to_string()
} else {
"[VALID_TOKEN_HASHED]".to_string()
}
} else {
"[MISSING_BEARER_PREFIX]".to_string()
}
}
// Usage in Actix extractor or handler:
let token = sanitize_bearer_token(auth_str);
log::debug!(token_status = %token);
Example 3: Combining with Actix logging guards to avoid accidental exposure
Use guards to ensure that logging only occurs when safe conditions are met, and avoid logging in error paths where raw headers might be captured inadvertently.
use actix_web::dev::ServiceRequest;
use actix_web::Error;
use actix_web::http::header::HeaderValue;
fn authorized_and_safe(req: &ServiceRequest) -> bool {
if let Some(header_value) = req.headers().get(&actix_web::http::header::AUTHORIZATION) {
if let Ok(val) = header_value.to_str() {
return val.starts_with("Bearer ") && !val.contains('\n');
}
}
false
}
// In a wrapper or guard implementation:
if authorized_and_safe(&request) {
log::info!("Request authorized, proceeding");
} else {
log::warn!("Unauthorized or unsafe authorization header");
}
These practices ensure that Bearer Tokens are treated as untrusted input, preventing log injection while preserving the ability to audit and debug safely. The approach aligns with secure handling of authentication material in Actix-based services.