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.
Bayangkan pembaca kartu kunci hotel yang hanya boleh membuka kamar di lantai dua. Jika seorang tamu mengetik '../../master-safe' pada tombol pintu, kunci yang rentan keluar ke lorong dan membuka brankas utama milik manajer.
Web Application SecurityCWE-918.CWE-918Defense-in-DepthTitik akhir menerima nama file atau pengenal sumber daya dari parameter permintaan HTTP.
Penyerang menyisipkan urutan traversal seperti '../', '..%2f' atau jalur mutlak ke parameter file.
Backend menggabungkan nama file tanpa kanonisasi jalur dan tanpa memastikan target tetap dalam folder aman.
Sistem membaca dan mengalirkan file sensitif (misal: /etc/passwd atau rahasia konfigurasi) ke klien.
// 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.