flawopen.com/path-traversal/Swift
How file path operations in Swift/Vapor allow traversal escapes, and how to enforce boundaries using standardizedFileURL and standardized paths.
Imaginez un lecteur de carte d'hôtel programmé pour n'ouvrir que les chambres du 2e étage. Si un client tape '../../master-safe' sur le digicode, la serrure vulnérable remonte le couloir et déverrouille le coffre-fort principal du gérant.
Web Application SecurityCWE-918.CWE-918Defense-in-DepthUn point de terminaison accepte un nom de fichier ou un identifiant de ressource via un paramètre HTTP.
L'attaquant injecte des séquences relatives comme '../', '..%2f' ou des chemins absolus non autorisés.
Le backend concatène naïvement le fichier sans vérifier le chemin canonique ni restreindre le répertoire racine.
Le runtime ouvre et renvoie des fichiers système critiques (/etc/passwd, secrets d'API) à l'attaquant.
// VULNERABLE: PathBuf::join allows directory traversal
use std::fs;
use std::path::PathBuf;
fn read_user_file(filename: &str) -> Result<Vec<u8>, std::io::Error> {
let base_dir = PathBuf::from("/var/app/public/files");
// Attacker input: "../../etc/passwd"
let target = base_dir.join(filename);
// Reads arbitrary system files!
fs::read(target)
}
// HARDENED: Canonicalize path and assert directory prefix
use std::fs;
use std::path::{Path, PathBuf};
use std::io::{Error, ErrorKind};
fn read_user_file(filename: &str) -> Result<Vec<u8>, Error> {
let base_dir = Path::new("/var/app/public/files").canonicalize()?;
// 1. Join and canonicalize target path (resolves .. and symlinks)
let target = base_dir.join(filename);
let resolved = target.canonicalize()?;
// 2. Strict boundary check: resolved must start with base_dir
if !resolved.starts_with(&base_dir) {
return Err(Error::new(ErrorKind::PermissionDenied, "Path traversal attempt detected"));
}
if !resolved.is_file() {
return Err(Error::new(ErrorKind::NotFound, "File not found"));
}
fs::read(resolved)
}
resolved.is_file() before reading.