Formula Injection in Actix with Bearer Tokens
Formula Injection in Actix with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Formula Injection occurs when user-controlled data is interpreted as a formula (e.g., Excel or CSV formulas) by downstream systems, leading to unintended code execution or data manipulation. In an Actix web service that accepts CSV or spreadsheet uploads and uses Bearer Tokens for authorization, combining these elements can expose security risks.
Consider an endpoint that receives an uploaded CSV file and an Authorization header containing a Bearer Token. If the CSV content is later processed by a downstream system (such as a reporting tool or data import pipeline) without sanitization, a malicious actor could embed formulas like =cmd|' /C calc'!A0 or =HYPERLINK("https://evil.example.com") into cells. When an authorized user with a valid Bearer Token downloads or views the processed file, the injected formula may execute in their context, leveraging their permissions.
The Bearer Token itself does not cause the injection, but it facilitates access to sensitive endpoints where file processing occurs. If the API does not validate or sanitize uploaded content, an authenticated request (with a valid Bearer Token) can lead to unauthorized actions being performed on behalf of the user. For example, an attacker might use a valid token to submit a crafted CSV through an Actix handler, then trick an internal user into opening the file, triggering the embedded formula.
In Actix, a typical handler might look like this, illustrating how a token is checked before processing an upload:
use actix_web::{web, HttpRequest, HttpResponse};
async fn upload_csv(
req: HttpRequest,
payload: web::Payload,
) -> Result {
// Extract Bearer token
let auth_header = req.headers().get("Authorization");
let token = match auth_header {
Some(h) => h.to_str().unwrap_or("").strip_prefix("Bearer ").unwrap_or(""),
None => return Ok(HttpResponse::Unauthorized().finish()),
};
if token.is_empty() {
return Ok(HttpResponse::Unauthorized().finish());
}
// Process CSV (vulnerable if content is not sanitized)
let body = web::block(move || {
let mut reader = csv::Reader::from_reader(payload);
for result in reader.records() {
let record = result?;
// Further processing or storage
}
Ok::<_, actix_web::Error>(())
})
.await??;
Ok(HttpResponse::Ok().body("Processed"))
}
If the CSV is later exported or rendered in a tool that interprets formulas, the injected content may execute. This risk is compounded when tokens grant access to sensitive internal endpoints where files are processed with higher privileges.
Real-world examples include CVE-2022-32831, where formula injection in spreadsheet software led to remote code execution, and patterns seen in OWASP API Top 10’s Broken Object Level Authorization (BOLA) when file handling lacks strict validation. middleBrick scans would flag such issues under Input Validation and BOLA checks when testing authenticated attack surfaces.
Bearer Tokens-Specific Remediation in Actix — concrete code fixes
Remediation focuses on sanitizing uploaded content and strictly validating authorization context. Even when Bearer Tokens are used correctly for authentication, the API must treat uploaded data as untrusted.
First, avoid processing raw CSV content directly. Instead, parse and sanitize each cell, stripping or escaping formula-like patterns. Use a strict allowlist for expected data formats.
Second, ensure Bearer Token validation is consistent and does not leak scope. Use middleware to verify token format and scope before allowing access to file-processing endpoints.
Here is a revised Actix handler that implements safer handling:
use actix_web::{web, HttpRequest, HttpResponse};
use csv::StringRecord;
fn is_safe_record(record: &StringRecord) -> bool {
// Reject cells that start with common formula indicators
record.iter().all(|cell| {
let trimmed = cell.trim();
!(trimmed.starts_with('=')
|| trimmed.starts_with('+')
|| trimmed.starts_with('-')
|| trimmed.starts_with('@'))
})
}
async fn upload_csv_safe(
req: HttpRequest,
payload: web::Payload,
) -> Result {
// Validate Bearer Token format early
let auth_header = req.headers().get("Authorization");
let token = match auth_header {
Some(h) => {
let t = h.to_str().unwrap_or("").strip_prefix("Bearer ").unwrap_or("");
if t.is_empty() || !t.chars().all(|c| c.is_alphanumeric() || c == '-' || c == '_') {
return Ok(HttpResponse::Unauthorized().finish());
}
t
}
None => return Ok(HttpResponse::Unauthorized().finish()),
};
// Process CSV with sanitization
let body = web::block(move || {
let mut reader = csv::Reader::from_reader(payload);
for result in reader.records() {
let record: StringRecord = result?;
if !is_safe_record(&record) {
return Err(actix_web::error::ErrorBadRequest("Unsafe content detected"));
}
// Safe processing continues
}
Ok::<_, actix_web::Error>(())
})
.await??;
Ok(HttpResponse::Ok().body("Processed safely"))
}
Key changes include:
- A
is_safe_recordfunction that rejects cells starting with formula indicators (=,+,-,@). - Strict token format validation, ensuring the Bearer Token contains only expected characters and is not empty.
- Early rejection of malformed or suspicious payloads before deeper processing.
These steps reduce the risk of formula injection when combined with proper input validation checks that middleBrick would highlight under its Input Validation and BOLA assessments.