From 1423c8d20aa42c6c30efe81af3d9b2ae7ca15073 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sun, 21 Jun 2026 16:10:48 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=94=92=20Fix=20path=20traversal=20vul?= =?UTF-8?q?nerability=20in=20cacheRoot=20and=20tempRoot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pr_description.md | 10 ++++++ .../src/bandscope_analysis/api.py | 4 +++ services/analysis-engine/tests/test_api.py | 32 +++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 pr_description.md diff --git a/pr_description.md b/pr_description.md new file mode 100644 index 00000000..7b9174f4 --- /dev/null +++ b/pr_description.md @@ -0,0 +1,10 @@ +🔒 Fix path traversal vulnerability in cacheRoot and tempRoot + +🎯 **What:** The vulnerability fixed +A path traversal vulnerability in `services/analysis-engine/src/bandscope_analysis/api.py` via the `cacheRoot` and `tempRoot` request parameters. The parameters were being concatenated without proper sanitization. + +⚠️ **Risk:** The potential impact if left unfixed +A malicious payload containing `../` in `cacheRoot` or `tempRoot` could allow a user or another process to write cache and temp files outside of the designated directories (e.g. overwriting critical system files or unauthorized access to other directories). + +🛡️ **Solution:** How the fix addresses the vulnerability +Added explicit validation logic within `validate_analysis_job_request` to reject any `cacheRoot` or `tempRoot` path that contains `..`. This effectively blocks basic directory ascension payloads. Added corresponding test cases in `test_api.py`. diff --git a/services/analysis-engine/src/bandscope_analysis/api.py b/services/analysis-engine/src/bandscope_analysis/api.py index a193bce2..e44bf7de 100644 --- a/services/analysis-engine/src/bandscope_analysis/api.py +++ b/services/analysis-engine/src/bandscope_analysis/api.py @@ -307,10 +307,14 @@ def validate_analysis_job_request(payload: object) -> AnalysisJobRequest: if cache_root is not None: if not isinstance(cache_root, str) or not cache_root.strip(): raise ValueError("Invalid analysis job request: invalid field 'cacheRoot'") + if ".." in cache_root: + raise ValueError("Invalid analysis job request: invalid field 'cacheRoot'") normalized["cacheRoot"] = cache_root if temp_root is not None: if not isinstance(temp_root, str) or not temp_root.strip(): raise ValueError("Invalid analysis job request: invalid field 'tempRoot'") + if ".." in temp_root: + raise ValueError("Invalid analysis job request: invalid field 'tempRoot'") normalized["tempRoot"] = temp_root return normalized diff --git a/services/analysis-engine/tests/test_api.py b/services/analysis-engine/tests/test_api.py index ea55cba2..e6da6e43 100644 --- a/services/analysis-engine/tests/test_api.py +++ b/services/analysis-engine/tests/test_api.py @@ -245,6 +245,38 @@ def test_validate_analysis_job_request_rejects_bad_payloads() -> None: }, "cacheRoot", ), + ( + { + "sourceKind": "local_audio", + "projectId": "project-1", + "sourceLabel": "Late Night Set", + "roleFocus": [], + "localSource": { + "sourcePath": "/Users/test/Music/late-night-set.wav", + "fileName": "late-night-set.wav", + "extension": "wav", + "fileSizeBytes": 1024000, + }, + "cacheRoot": "/tmp/../../../etc", + }, + "cacheRoot", + ), + ( + { + "sourceKind": "local_audio", + "projectId": "project-1", + "sourceLabel": "Late Night Set", + "roleFocus": [], + "localSource": { + "sourcePath": "/Users/test/Music/late-night-set.wav", + "fileName": "late-night-set.wav", + "extension": "wav", + "fileSizeBytes": 1024000, + }, + "tempRoot": "/tmp/../../../etc", + }, + "tempRoot", + ), ( { "sourceKind": "local_audio", From 3cb931921bd19d9111b926a069da4de99d62a78e Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sun, 21 Jun 2026 18:06:11 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=94=92=20Fix=20path=20traversal=20vul?= =?UTF-8?q?nerability=20in=20cacheRoot=20and=20tempRoot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pr_description.md | 10 ---------- test_fix.py | 10 ++++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) delete mode 100644 pr_description.md create mode 100644 test_fix.py diff --git a/pr_description.md b/pr_description.md deleted file mode 100644 index 7b9174f4..00000000 --- a/pr_description.md +++ /dev/null @@ -1,10 +0,0 @@ -🔒 Fix path traversal vulnerability in cacheRoot and tempRoot - -🎯 **What:** The vulnerability fixed -A path traversal vulnerability in `services/analysis-engine/src/bandscope_analysis/api.py` via the `cacheRoot` and `tempRoot` request parameters. The parameters were being concatenated without proper sanitization. - -⚠️ **Risk:** The potential impact if left unfixed -A malicious payload containing `../` in `cacheRoot` or `tempRoot` could allow a user or another process to write cache and temp files outside of the designated directories (e.g. overwriting critical system files or unauthorized access to other directories). - -🛡️ **Solution:** How the fix addresses the vulnerability -Added explicit validation logic within `validate_analysis_job_request` to reject any `cacheRoot` or `tempRoot` path that contains `..`. This effectively blocks basic directory ascension payloads. Added corresponding test cases in `test_api.py`. diff --git a/test_fix.py b/test_fix.py new file mode 100644 index 00000000..dcdc685e --- /dev/null +++ b/test_fix.py @@ -0,0 +1,10 @@ +import re + +with open(".github/workflows/opencode-review.yml", "r") as f: + content = f.read() + +# Let's find why the process completed with exit code 1 +# Specifically at Line: 1782 +# --title "PR #${PR_NUMBER} failed-check diagnosis ${MODEL}" >"$opencode_json_file"; then + +print(content[content.find("1782"):content.find("1782")+200])