fix(security): guard GitRepositoryService.diff against unsafe refs

Brakeman flagged the three-dot diff command added for get_pull_request: base and head reach git as a single interpolated argv entry, so a ref starting with "-" would be parsed as an option rather than a revision, the same git-argument-injection class the rest of this file already guards against. diff now rejects either ref via safe_rev? before calling git, matching every other method here, and the finding is triaged into brakeman.ignore with the same note style as its siblings.

Seto Elkahfi committed Jul 5, 2026 at 11:39 UTC 987857cc6831fe155aaa0767733a847b5f515ef7
2 files changed +13 -1
app/services/git_repository_service.rb
+3 -1
index ed03905..d1f1718 100644 --- a/app/services/git_repository_service.rb +++ b/app/services/git_repository_service.rb @@ -221,8 +221,10 @@ class GitRepositoryService # Unified diff of +head+ against its merge base with +base+ (three-dot # `git diff base...head`, the same range a pull request shows). Returns the # diff String ("" when the refs are identical), or nil when either ref is - # unknown or the repository is missing. + # unknown, unsafe, or the repository is missing. def self.diff(path, base, head) + return nil unless safe_rev?(base) && safe_rev?(head) + out, _err, status = Open3.capture3("git", "--git-dir", path, "diff", "#{base}...#{head}") return nil unless status.success? out
config/brakeman.ignore
+10
index ae0aa8c..07230fc 100644 --- a/config/brakeman.ignore +++ b/config/brakeman.ignore @@ -1,5 +1,15 @@ { "ignored_warnings": [ + { + "warning_type": "Command Injection", + "warning_code": 14, + "fingerprint": "03f0108aa182ee54b38be945afcbe9c90ffec86500b284510dae38fff5a2d1e0", + "check_name": "Execute", + "message": "Possible command injection", + "file": "app/services/git_repository_service.rb", + "line": 228, + "note": "False positive: Open3.capture3 is called with a separate argument list (no shell), so the interpolated base/head refs are passed to git as a single literal argv entry and cannot inject shell commands. GitRepositoryService.safe_rev? rejects either ref if it starts with \"-\" before it reaches git, closing the git-argument-injection surface (e.g. a base of \"--output=...\")." + }, { "warning_type": "Command Injection", "warning_code": 14,