HIGH path traversalactixmutual tls

Path Traversal in Actix with Mutual Tls

Path Traversal in Actix with Mutual Tls — how this specific combination creates or exposes the vulnerability

Path Traversal occurs when user-controlled input is used to construct file system paths without proper validation, allowing an attacker to read or write files outside the intended directory. In Actix web applications, this typically manifests through endpoints that accept a filename or path parameter and directly concatenate it with a base directory. When Mutual TLS (mTLS) is enforced, the server validates client certificates, which may create a false sense of strong authentication. Operators might assume that because only authorized clients can reach the endpoint, input validation is less critical. This is incorrect: mTLS secures channel identity but does not restrict what an authenticated client can request. An authorized client can still send crafted paths such as ../../../etc/passwd. If the server does not canonicalize and validate the resulting path, the traversal succeeds. In Actix, a handler like async fn download(path: web::Path<String>) that joins the path to a base directory without normalization becomes vulnerable. The presence of mTLS does not mitigate this; it only ensures the request comes from a trusted client, not that the client’s input is safe. Therefore, the combination of Path Traversal and mTLS can lead to unauthorized file access because developers might conflate transport-layer identity with application-layer authorization.

Mutual Tls-Specific Remediation in Actix — concrete code fixes

Securing Path Traversal in Actix requires strict input validation and path canonicalization regardless of mTLS usage. Below are concrete code examples showing how to implement secure file-serving endpoints with proper checks. These examples assume you have configured mTLS in your Actix server (see the mTLS example further below) and now focus on safe path handling.

Secure Path Handling Example

Always resolve user input against a base directory and ensure the resolved path remains within that directory. Use Rust’s std::path::Path methods and avoid string concatenation.

use actix_web::{web, HttpResponse, Result};
use std::path::{Path, PathBuf};

/// Serve files only from a specific base directory, preventing traversal.
async fn safe_file_download(base_dir: web::Data<PathBuf>, requested_path: web::Path<String>) -> Result<HttpResponse> {
    // Normalize and sanitize the input: remove leading slashes, backslashes, and resolve "." and ".."
    let requested = Path::new(&requested_path).strip_prefix(".").unwrap_or(Path::new(&requested_path));
    // Build the full path ensuring it stays within base_dir
    let full_path = base_dir.join(requested);
    // Ensure the canonicalized path starts with the base directory
    let canonical_base = std::fs::canonicalize(base_dir.as_path()).map_err(|_| actix_web::error::ErrorInternalServerError("server misconfiguration"))?;
    let canonical_full = std::fs::canonicalize(&full_path).map_err(|_| actix_web::error::ErrorNotFound("file not found"))?;
    if !canonical_full.starts_with(&canonical_base) {
        return Err(actix_web::error::ErrorForbidden("access denied"));
    }
    actix_files::NamedFile::open(canonical_full).map_err(|_| actix_web::error::ErrorNotFound("file not found"))?.into_response(&actix_web::HttpRequest::default())
}

Key points:

  • strip_prefix(".") removes attempts to start traversal with . or ./.
  • canonicalize resolves symbolic links and normalizes .. segments; comparing the result to the canonical base ensures the file remains inside the allowed directory.
  • Return 404 instead of detailed errors to avoid leaking filesystem information.

Mutual Tls Configuration Example for Actix

This example shows how to configure mTLS in Actix using actix-web and rustls. Note that mTLS ensures client certificate validation at the TLS layer, but does not replace secure path handling.

use actix_web::{App, HttpServer, web};
use actix_files as fs;
use std::sync::Arc;
use rustls::{ServerConfig, Certificate, PrivateKey};
use rustls_pemfile::{certs, pkcs8_private_keys};
use std::io::BufReader;
use std::fs::File;

async fn run_secure_server() -> std::io::Result<()> {
    // Load server certificate and private key
    let cert_file = &mut BufReader::new(File::open("server-cert.pem").expect("cannot open server cert"));
    let key_file = &mut BufReader::new(File::open("server-key.pem").expect("cannot open server key"));

    let cert_chain: Vec<Certificate> = certs(cert_file).unwrap().into_iter().map(Certificate).collect();
    let mut keys: Vec<PrivateKey> = pkcs8_private_keys(key_file).unwrap().into_iter().map(PrivateKey).collect();

    let mut server_config = ServerConfig::builder()
        .with_safe_defaults()
        .with_no_client_auth() // Start without client auth, then enable via set_client_cert_verifier
        .with_single_cert(cert_chain, keys.remove(0))
        .expect("bad server cert or key");

    // Enable client certificate verification (mTLS)
    server_config.client_auth_root_subjects = Arc::new(...); // Load trusted CA certificates
    server_config.verify_peer = true;

    HttpServer::new(move || {
        App::new()
            .app_data(web::Data::new(std::env::current_dir().unwrap())) // base directory for file access
            .route("/files/{path:.*}", web::get().to(safe_file_download))
    })
    .bind_rustls("127.0.0.1:8443", server_config)?
    .run()
    .await
}

With mTLS enabled, clients must present a valid certificate trusted by the server. However, the application must still validate file paths as shown above. Relying on mTLS alone to prevent Path Traversal is insufficient.

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Does enabling Mutual TLS in Actix automatically prevent Path Traversal vulnerabilities?
No. Mutual TLS authenticates the client at the transport layer but does not validate or sanitize file path inputs. An authenticated client can still send paths like ../../../secret.txt. You must implement path canonicalization and strict validation in your handler to prevent traversal.
How does middleBrick relate to Path Traversal findings in Actix with mTLS?
middleBrick scans endpoints without credentials and includes checks for Path Traversal across authentication configurations. If your Actix API uses mTLS, middleBrick will test the unauthenticated attack surface and can identify Path Traversal findings regardless of TLS client cert requirements. Its reports map to frameworks like OWASP API Top 10 and provide remediation guidance, helping you prioritize fixes for unsafe path handling.