HIGH crlf injectionaxumfirestore

Crlf Injection in Axum with Firestore

Crlf Injection in Axum with Firestore — how this specific combination creates or exposes the vulnerability

Crlf Injection occurs when user-controlled data is inserted into HTTP headers or logs without sanitization, allowing an attacker to inject newline characters (%0D%0A or \r\n). In an Axum application that interfaces with Google Firestore, this typically arises when response headers or log entries are built from Firestore document fields that an attacker can influence.

Consider an endpoint that retrieves a user profile from Firestore and sets a custom header such as x-user-name from a Firestore field. If the field contains a CRLF sequence, Axum will include that sequence in the outgoing HTTP message when the response is serialized by the underlying hyper stack. An attacker can use this to split headers, inject additional headers, or perform HTTP response splitting. In Firestore, a document might store a display name like Bob%0D%0ASet-Cookie:%20session=attacker. When this value is read and used as a header value, the injected line is interpreted by the client or intermediary proxy as a separate header, enabling cache poisoning, cross-user manipulation, or information disclosure.

Logging is another exposure path. If Axum logs request metadata and includes a Firestore field (e.g., a user-supplied note or tag) in the log line without sanitization, a CRLF sequence can forge new log entries. This can obscure real events or inject fake entries into centralized logging pipelines. Although Firestore itself does not execute injected content, the data becomes a vector when consumed by Axum’s runtime components. The risk is compounded when Firestore documents are used to construct URLs or redirect targets, where CRLF injection can facilitate open redirects or header manipulation.

Because Axum is a minimal, composable web framework, it does not automatically sanitize inputs coming from external services such as Firestore. Developers must treat any data sourced from Firestore as untrusted when it flows into headers, logs, or any serialization boundary. The unauthenticated scan capability of middleBrick can surface these weaknesses by tracing data flows from Firestore reads into HTTP responses and logs, flagging missing output encoding and header validation.

Firestore-Specific Remediation in Axum — concrete code fixes

Remediation focuses on two areas: preventing CRLF characters from Firestore fields from reaching HTTP headers or logs, and validating/sanitizing data at the boundary between Firestore and Axum. Below are concrete Axum handler examples with Firestore integration that demonstrate safe patterns.

1. Header Construction with Sanitization

Never directly assign Firestore document fields to headers. Strip or reject CRLF characters before use. Here is an Axum handler that reads a Firestore document and sets a sanitized header:

use axum::{routing::get, Router, response::IntoResponse, headers::HeaderMapExt};
use google_cloud_firestore::client::Client;
use std::convert::Infallible;

async fn user_profile_handler(
    user_id: String,
    firestore_client: &Client,
) -> Result {
    let doc_ref = firestore_client.collection("users").doc(&user_id);
    let snapshot = doc_ref.get().await.map_err(|_| Infallible)?;
    let display_name: String = snapshot.get("display_name").unwrap_or_default();
    // Sanitize: remove CRLF characters to prevent header injection
    let safe_name = display_name.replace("\r", "").replace("\n", "");
    let mut headers = HeaderMapExt::new();
    headers.insert("x-user-name", safe_name.parse().unwrap());
    Ok((headers, axum::Json(serde_json::json!({ "ok": true }))))
}

2. Logging with Controlled Formatting

When logging Firestore-derived values, avoid raw inclusion. Use a logging facade that does not interpret newlines as structured entries, or explicitly remove line breaks:

use tracing::info;

fn log_user_action(user_id: &str, note: &str) {
    // Remove CRLF before logging to prevent log forging
    let safe_note = note.replace("\r", " ").replace("\n", " ");
    info!(user_id = %user_id, note = %safe_note, "user_action");
}

3. Input Validation at the API Boundary

Apply allow-lists or strict sanitization on Firestore fields that originate from user input, especially if those fields later influence HTTP semantics. For example, validate display names to exclude control characters before storing or using them in headers:

fn is_printable_without_crlf(s: &str) -> bool {
    s.chars().all(|c| c.is_ascii_graphic() || c == ' ')
        && !s.contains("\r") && !s.contains("\n")
}

async fn create_user_handler(
    axum::Json(payload): axum::Json<CreateUserPayload>,
    firestore_client: &Client,
) -> Result<impl IntoResponse, Infallible> {
    if !is_printable_without_crlf(&payload.display_name) {
        return Ok((StatusCode::BAD_REQUEST, axum::Json(serde_json::json!({ "error": "invalid_display_name" })));
    }
    let doc_ref = firestore_client.collection("users").doc(&payload.user_id);
    doc_ref.set(serde_json::to_dict(&payload).unwrap(), None).await.map_err(|_| Infallible)?;
    Ok(StatusCode::CREATED)
}

4. Middleware-Level Sanitization

For broader protection, implement an Axum layer that scans outgoing headers for CRLF patterns and rejects or rewrites them. This complements Firestore-side validation:

use axum::{Layer, ServiceBuilder, async_trait};
use tower_http::trace::TraceLayer;

// Example: a custom layer that ensures headers are safe before sending
fn safe_headers_layer() -> impl Layer<axum::Router> {
    ServiceBuilder::new().layer_fn(|service| {
        tower::service_fn(move |req: axum::http::Request<axum::body::Body>| {
            let mut res = service.call(req).await;
            if let Ok(headers) = res.as_mut().map(|r| r.headers_mut()) {
                for (_, value) in headers.iter_mut() {
                    let v = value.to_str().unwrap_or("").replace("\r", "").replace("\n", "");
                    *value = v.parse().unwrap_or_default();
                }
            }
            res
        })
    })
}

By combining Firestore data validation, header sanitization, and careful logging practices, Axum applications can neutralize CRLF injection risks while still leveraging Firestore as a backend store. middleBrick scans can verify that such mitigations are present by tracing data flows and flagging endpoints where user-influenced Firestore data reaches headers or logs without sanitization.

Frequently Asked Questions

Can Firestore itself prevent CRLF injection if I use security rules?
Firestore security rules can restrict what data can be written, but they do not automatically sanitize data for HTTP header usage. You must still sanitize or reject CRLF characters in Axum before using Firestore fields in headers or logs; rules alone are not sufficient.
Does middleBrick detect CRLF injection in Axum apps that use Firestore?
Yes. middleBrick scans unauthenticated attack surfaces and traces data flows from sources like Firestore into HTTP responses and logs, identifying missing sanitization that could enable CRLF injection.