From 80a4a04cca2325bf205d6d6db0a02ea4876f5428 Mon Sep 17 00:00:00 2001 From: Guy Vago Date: Tue, 14 Apr 2026 13:43:47 +0300 Subject: [PATCH 1/3] fix(gerrit): prevent path traversal in publish_code_suggestions Sanitize the `relevant_file` path before writing to prevent directory traversal attacks. The path is resolved and verified to stay within `repo_path` before any file write occurs. Suggestions with suspicious paths are skipped with a warning log. Co-Authored-By: Claude Opus 4.6 (1M context) --- pr_agent/git_providers/gerrit_provider.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pr_agent/git_providers/gerrit_provider.py b/pr_agent/git_providers/gerrit_provider.py index ced150c915..3699c09dae 100644 --- a/pr_agent/git_providers/gerrit_provider.py +++ b/pr_agent/git_providers/gerrit_provider.py @@ -342,10 +342,16 @@ def split_suggestion(self, msg) -> tuple[str, str]: def publish_code_suggestions(self, code_suggestions: list): msg = [] + repo_root = pathlib.Path(self.repo_path).resolve() for suggestion in code_suggestions: + # Sanitize file path to prevent directory traversal + target_path = (repo_root / suggestion["relevant_file"]).resolve() + if not str(target_path).startswith(str(repo_root)): + get_logger().warning(f"Skipping suggestion with path traversal: {suggestion['relevant_file']}") + continue description, code = self.split_suggestion(suggestion['body']) add_suggestion( - pathlib.Path(self.repo_path) / suggestion["relevant_file"], + target_path, code, suggestion["relevant_lines_start"], suggestion["relevant_lines_end"], From a9332a287a83c18af7a93e07d9ad9c20f9b56ca5 Mon Sep 17 00:00:00 2001 From: Guy Vago Date: Tue, 14 Apr 2026 13:49:12 +0300 Subject: [PATCH 2/3] fix: address Qodo review - validate suggestion dict, use relative_to for path check --- pr_agent/git_providers/gerrit_provider.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pr_agent/git_providers/gerrit_provider.py b/pr_agent/git_providers/gerrit_provider.py index 3699c09dae..ad669b54d5 100644 --- a/pr_agent/git_providers/gerrit_provider.py +++ b/pr_agent/git_providers/gerrit_provider.py @@ -344,9 +344,15 @@ def publish_code_suggestions(self, code_suggestions: list): msg = [] repo_root = pathlib.Path(self.repo_path).resolve() for suggestion in code_suggestions: + # Validate suggestion structure before accessing keys + if not isinstance(suggestion, dict) or not isinstance(suggestion.get("relevant_file"), str): + get_logger().warning(f"Skipping malformed suggestion: missing or invalid 'relevant_file'") + continue # Sanitize file path to prevent directory traversal - target_path = (repo_root / suggestion["relevant_file"]).resolve() - if not str(target_path).startswith(str(repo_root)): + try: + target_path = (repo_root / suggestion["relevant_file"]).resolve() + target_path.relative_to(repo_root) + except ValueError: get_logger().warning(f"Skipping suggestion with path traversal: {suggestion['relevant_file']}") continue description, code = self.split_suggestion(suggestion['body']) From 1dcc22ef05987777cf28db57be68bf2707e98e2f Mon Sep 17 00:00:00 2001 From: Guy Vago Date: Wed, 15 Apr 2026 09:22:03 +0300 Subject: [PATCH 3/3] fix: address Qodo review - remove useless f-string prefix Co-Authored-By: Claude Opus 4.6 (1M context) --- pr_agent/git_providers/gerrit_provider.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pr_agent/git_providers/gerrit_provider.py b/pr_agent/git_providers/gerrit_provider.py index ad669b54d5..be0de5354c 100644 --- a/pr_agent/git_providers/gerrit_provider.py +++ b/pr_agent/git_providers/gerrit_provider.py @@ -346,7 +346,7 @@ def publish_code_suggestions(self, code_suggestions: list): for suggestion in code_suggestions: # Validate suggestion structure before accessing keys if not isinstance(suggestion, dict) or not isinstance(suggestion.get("relevant_file"), str): - get_logger().warning(f"Skipping malformed suggestion: missing or invalid 'relevant_file'") + get_logger().warning("Skipping malformed suggestion: missing or invalid 'relevant_file'") continue # Sanitize file path to prevent directory traversal try: