HIGH zip slipactix

Zip Slip in Actix

How Zip Slip Manifests in Actix

Zip Slip in Actix applications typically occurs when handling file uploads or archive extraction without proper path validation. Actix, being a Rust-based web framework, often processes multipart form data or archive files that can contain malicious path traversal sequences.

The vulnerability manifests when Actix endpoints accept ZIP files or other archives and extract them to a target directory. Attackers can craft archive entries with paths like ../../etc/passwd or subdir/../../../target to overwrite critical files outside the intended extraction directory.

In Actix applications, this commonly appears in code patterns like:

async fn upload_archive(mut payload: Payload) -> impl Responder {
let mut multipart = Multipart::new(payload);
while let Some(field) = multipart.next().await {
let field = field.unwrap();
let content_type = field.content_disposition();
let filename = content_type.get_filename().unwrap();
let filepath = format!("/tmp/uploads/{}", filename);
let mut file = File::create(filepath).await.unwrap();
while let Some(chunk) = field.next().await {
file.write_all(&chunk.unwrap()).await.unwrap();
}
}
HttpResponse::Ok().finish()
}

The critical issue is that filename comes directly from the client without validation. An attacker can submit ../../../etc/passwd as the filename, causing Actix to write outside the intended directory.

Archive extraction is even more dangerous:

async fn extract_zip(file: web::Bytes) -> impl Responder {
let reader = std::io::Cursor::new(file);
let mut archive = zip::ZipArchive::new(reader).unwrap();
for i in 0..archive.len() {
let mut file = archive.by_index(i).unwrap();
let outpath = file.enclosed_name().unwrap().unwrap();
let mut outfile = File::create(outpath).await.unwrap();
io::copy(&mut file, &mut outfile).await.unwrap();
}
HttpResponse::Ok().finish()
}

Even with enclosed_name() from the zip crate, if not properly handled, path traversal can still occur. The outpath might resolve to locations outside the intended extraction directory.

Actix's async nature means these operations happen without blocking the event loop, but the security implications remain severe. An attacker exploiting Zip Slip through Actix could overwrite configuration files, inject malicious code into application directories, or access sensitive system files.

Actix-Specific Detection

Detecting Zip Slip in Actix applications requires examining both the code patterns and runtime behavior. The middleBrick API security scanner includes specific detection capabilities for Actix applications, focusing on the unique ways this vulnerability manifests in Rust web services.

middleBrick's detection engine identifies Zip Slip through several Actix-specific patterns:

  1. Multipart form handlers that accept file uploads without path validation
  2. Archive extraction endpoints that process ZIP, TAR, or other archive formats
  3. Dynamic file path construction using client-supplied data
  4. Unsafe use of path joining operations without canonicalization

When scanning an Actix application, middleBrick tests for Zip Slip by submitting crafted payloads with path traversal sequences. For example, it might submit a multipart form with a filename like ../../../malicious.txt and observe whether the server writes the file outside the intended directory.

The scanner also examines OpenAPI specifications for Actix applications, looking for endpoints that accept file uploads or archive processing. It cross-references these specifications with runtime behavior to identify discrepancies between documented and actual behavior.

middleBrick's LLM security features are particularly relevant for Actix applications that might process AI-generated content. If an Actix endpoint accepts user uploads that could contain malicious archives generated by AI systems, the scanner tests for both traditional Zip Slip and AI-specific attack patterns.

Key detection indicators include:

// Patterns middleBrick flags:
let filepath = format!("/uploads/{}", user_input); // NO validation
let path = Path::new(&dir).join(user_filename); // NO canonicalization
let target = archive.extract(dir).unwrap(); // NO path validation

The scanner provides Actix-specific remediation guidance, noting that Rust's standard library offers path manipulation functions that can prevent Zip Slip when used correctly.

Actix-Specific Remediation

Remediating Zip Slip in Actix applications requires implementing proper path validation and using Rust's security features. The key is to ensure that all file operations remain within a designated safe directory.

The most effective approach is using path canonicalization and validation:

use actix_web::{web, HttpResponse, Responder};
use std::path::{Path, PathBuf};
use tokio::fs;
async fn safe_upload(file: web::Bytes, target_dir: web::Path<String>) -> impl Responder {
let target_dir = target_dir.into_inner();
let target_path = Path::new(&target_dir);

// Validate that target_dir is within allowed base directory
let base_dir = Path::new("/var/app/uploads");
let canonical_base = fs::canonicalize(base_dir).await.unwrap();
let canonical_target = fs::canonicalize(target_path).await.unwrap();

if !canonical_target.starts_with(canonical_base) {
return HttpResponse::BadRequest().body("Invalid target directory");
}

// Process file safely
HttpResponse::Ok().finish()
}

For archive extraction, use the zip crate's built-in safety features combined with additional validation:

async fn safe_extract_zip(file: web::Bytes) -> impl Responder {
let reader = std::io::Cursor::new(file);
let mut archive = zip::ZipArchive::new(reader).unwrap();
let extract_dir = "/var/app/uploads";

for i in 0..archive.len() {
let mut file = archive.by_index(i).unwrap();

// Get and validate the path
if let Some(path) = file.enclosed_name() {
let path = path.to_owned();
let full_path = Path::new(extract_dir).join(path);

// Canonicalize and validate
let canonical_full = fs::canonicalize(&full_path).await.unwrap();
let canonical_extract = fs::canonicalize(extract_dir).await.unwrap();

if !canonical_full.starts_with(canonical_extract) {
return HttpResponse::BadRequest().body("Path traversal detected");
}

// Create directories and write file
if let Some(parent) = full_path.parent() {
fs::create_dir_all(parent).await.unwrap();
}
let mut outfile = File::create(full_path).await.unwrap();
io::copy(&mut file, &mut outfile).await.unwrap();
} else {
return HttpResponse::BadRequest().body("Invalid archive entry");
}
}

HttpResponse::Ok().finish()
}

Actix-specific best practices include:

  • Always validate and canonicalize paths before file operations
  • Use Rust's Path::canonicalize() to resolve symlinks and relative paths
  • Implement strict directory whitelisting for file operations
  • Log and alert on path traversal attempts
  • Use Actix's built-in validation middleware for file uploads

For applications using Actix with AI features, ensure that any LLM-generated content or model outputs are also validated before processing as file paths or archive contents.

Frequently Asked Questions

How does middleBrick detect Zip Slip in Actix applications?
middleBrick scans Actix endpoints by submitting crafted payloads with path traversal sequences like '../../../etc/passwd'. It examines multipart form handlers and archive extraction endpoints for unsafe path construction patterns. The scanner also analyzes OpenAPI specs to identify file upload endpoints and tests them with malicious archive entries. middleBrick provides Actix-specific remediation guidance based on the detected patterns.
Can Zip Slip in Actix applications lead to remote code execution?
Yes, Zip Slip can enable remote code execution in Actix applications. If an attacker successfully overwrites executable files, configuration files, or injects malicious code into application directories, they can achieve code execution. The async nature of Actix means these operations happen efficiently, but without proper path validation, the security implications are severe. Always canonicalize paths and validate that file operations stay within designated safe directories.