Tar Extract Path Guard
Validate archive entry names before extraction, blocking absolute paths, parent traversal, and anything outside the destination.
Code
use std::path::{Component, Path, PathBuf};
fn safe_entry_path(destination: &Path, entry_name: &str) -> Result<PathBuf, String> {
let entry = Path::new(entry_name);
if entry.is_absolute() {
return Err(format!("absolute entry rejected: {entry_name}"));
}
let mut output = destination.to_path_buf();
let mut depth = 0usize;
for component in entry.components() {
match component {
Component::Normal(part) => {
output.push(part);
depth += 1;
}
Component::CurDir => {}
Component::ParentDir => {
if depth == 0 {
return Err(format!("entry escapes destination: {entry_name}"));
}
output.pop();
depth -= 1;
}
_ => return Err(format!("unsupported component in {entry_name}")),
}
}
if !output.starts_with(destination) {
return Err(format!("resolved entry escapes destination: {entry_name}"));
}
Ok(output)
}
fn main() {
let destination = Path::new("/var/lib/app/uploads");
let entries = [
"reports/2026.csv",
"docs/../notes.txt",
"../etc/cron.d/job",
"/etc/passwd",
"a/../../b",
];
for entry in entries {
match safe_entry_path(destination, entry) {
Ok(path) => println!("ok {entry:<22} => {}", path.display()),
Err(error) => println!("skip {entry:<22} => {error}"),
}
}
}Report a problem with this exampleOpens a pre-filled issue on GitHub.