-
Notifications
You must be signed in to change notification settings - Fork 6
Description
Summary
In src/cortex-app-server/src/api/files.rs, the list_files() handler accepts an arbitrary path from the request body and reads it directly with fs::read_dir without any path validation or traversal protection. Every other mutating file operation in the same file (write_file, delete_file) correctly calls validate_path_for_write / validate_path_for_delete from path_security.rs, but list_files and read_file are missing this check entirely.
Affected Code
// src/cortex-app-server/src/api/files.rs lines 27-87
pub async fn list_files(Json(req): Json<ListFilesRequest>) -> AppResult<Json<ListFilesResponse>> {
use std::fs;
let path = std::path::Path::new(&req.path); // ← raw, unvalidated path
if !path.exists() { ... }
if !path.is_dir() { ... }
let dir_entries = fs::read_dir(path) // ← reads arbitrary path
.map_err(...)?;
...
}Compare with write_file (line 225) which correctly validates:
let validated_path = validate_path_for_write(path).map_err(AppError::BadRequest)?;The same omission exists in read_file (line 193) and create_directory (line 282).
Root Cause
The validate_path_safe / validate_path_for_write helpers in path_security.rs enforce that paths stay within allowed roots (home directory, /workspace, /tmp, etc.) and resolve symlinks to prevent escapes. These checks were applied to write/delete operations but were not applied to read/list operations, presumably under the assumption that reading is harmless. However, listing and reading arbitrary paths is a significant information-disclosure vulnerability.
Impact
An authenticated (or unauthenticated, depending on middleware configuration) client can:
- List the contents of
/etc,/root,/proc, or any other directory on the host. - Read the contents of sensitive files such as
/etc/passwd,/etc/shadow,~/.ssh/id_rsa, environment files, or secret stores. - In containerised deployments, enumerate mounted secrets or service-account tokens.
Suggested Fix
Apply validate_path_safe before performing any filesystem read operation:
use super::path_security::validate_path_safe;
pub async fn list_files(Json(req): Json<ListFilesRequest>) -> AppResult<Json<ListFilesResponse>> {
let path = std::path::Path::new(&req.path);
let validated_path = validate_path_safe(path).map_err(AppError::BadRequest)?;
if !validated_path.exists() { ... }
if !validated_path.is_dir() { ... }
let dir_entries = fs::read_dir(&validated_path)?;
...
}Apply the same fix to read_file and create_directory.