From 7ba3b2b372db6eba559c31f3a362bf5dd03b02c2 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 28 May 2026 08:46:23 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[CRITICAL/H?= =?UTF-8?q?IGH]=20Fix=20path=20traversal=20in=20file=20download=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added a security check in `api/api_files_get.py` using `files.is_in_base_dir()` to ensure paths requested via the API are confined to the application base directory, preventing unauthorized access to the host filesystem via path traversal (e.g. `../../../etc/passwd`). Co-authored-by: thirdeyenation <133812267+thirdeyenation@users.noreply.github.com> --- .jules/sentinel.md | 4 ++++ api/api_files_get.py | 5 +++++ 2 files changed, 9 insertions(+) create mode 100644 .jules/sentinel.md diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000000..74de43c296 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2025-03-01 - Path Traversal in API Files Get Endpoint +**Vulnerability:** Found a critical path traversal vulnerability in `api/api_files_get.py` where user-provided paths (like `../../../etc/passwd`) were directly used to read and return file contents without verifying if they were within the application's base directory. +**Learning:** `files.get_abs_path()` uses `os.path.join` which resolves `..` paths naturally. But `os.path.join` on its own doesn't restrict paths to a specific root directory. Thus, absolute path resolution does not inherently prevent path traversal. +**Prevention:** Always validate resolved paths using `helpers.files.is_in_base_dir()` before performing file reading or writing operations based on user input. diff --git a/api/api_files_get.py b/api/api_files_get.py index b2533f4f4f..a9c6d72a96 100644 --- a/api/api_files_get.py +++ b/api/api_files_get.py @@ -62,6 +62,11 @@ async def process(self, input: dict, request: Request) -> dict | Response: external_path = path filename = os.path.basename(path) + # Security check: ensure path is within base directory to prevent path traversal + if not files.is_in_base_dir(external_path): + PrintStyle.warning(f"Access denied: path traversal detected for {path}") + continue + # Check if file exists if not os.path.exists(external_path): PrintStyle.warning(f"File not found: {path}")