Skip to content

Commit 4225893

Browse files
committed
Prevent path traversal for local storage
Signed-off-by: Denys Fedoryshchenko <denys.f@collabora.com>
1 parent f44ee51 commit 4225893

2 files changed

Lines changed: 18 additions & 1 deletion

File tree

src/local.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,20 @@ fn ensure_directory_exists(file_path: &Path) -> Result<(), std::io::Error> {
6666
fn get_storage_file_path(filename: &str) -> PathBuf {
6767
let config = get_local_config();
6868
let storage_path = Path::new(&config.storage_path);
69-
storage_path.join(filename)
69+
// Strip leading slashes to ensure the path is always relative to storage root
70+
let safe_name = filename.trim_start_matches('/');
71+
let full = storage_path.join(safe_name);
72+
// Defense-in-depth: verify resolved path stays within storage root
73+
let canonical_storage = storage_path.canonicalize().unwrap_or_else(|_| storage_path.to_path_buf());
74+
// Use the parent directory for canonicalization since the file may not exist yet
75+
let parent = full.parent().unwrap_or(&full);
76+
let canonical_parent = parent.canonicalize().unwrap_or_else(|_| parent.to_path_buf());
77+
if !canonical_parent.starts_with(&canonical_storage) {
78+
// Fall back to storage root to prevent escape
79+
storage_path.join(Path::new(safe_name).file_name().unwrap_or_default())
80+
} else {
81+
full
82+
}
7083
}
7184

7285
/// Get metadata file path for storing headers

src/main.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,8 @@ async fn ax_post_file(
693693
} else {
694694
format!("{}/{}", path, file0_filename)
695695
};
696+
// Normalize: strip leading slashes so the path is always relative
697+
let full_path = full_path.trim_start_matches('/').to_string();
696698

697699
// validate path for traversal
698700
match validate_path(&full_path) {
@@ -828,6 +830,8 @@ async fn ax_post_file(
828830
} else {
829831
format!("{}/{}", path, file0_filename)
830832
};
833+
// Normalize: strip leading slashes so the path is always relative
834+
let full_path = full_path.trim_start_matches('/').to_string();
831835

832836
match validate_path(&full_path) {
833837
Ok(_) => (),

0 commit comments

Comments
 (0)