Skip to content

[BUG] [v0.0.7] list_files() in api/files.rs has no path validation, allowing traversal to arbitrary filesystem paths #160

@katotomoya0105

Description

@katotomoya0105

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions