fix: address review findings (path restriction, login cross-check, README)
CI / test (pull_request) Successful in 14s
CI / review (gpt-4.1, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 19s
CI / review (gpt-5, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 1m15s
CI / review (gpt-5, security, SECURITY_REVIEW.md, SONNET_REVIEW_TOKEN) (pull_request) Successful in 1m20s

- system-prompt-file: reject absolute paths and paths containing ".."
  Prevents reading arbitrary files outside the workspace on shared runners.
- Cleanup: cross-check r.User.Login == posted.User.Login before deletion
  Defense-in-depth: only attempt to delete reviews from same author.
  Flagged by both sonnet and security reviewers.
- README: fix wording (cleanup happens after posting, not before)

Issues filed for deferred work:
- #24: Consistent url.PathEscape across all client endpoints
- #25: Binary signature verification for supply-chain hardening
This commit is contained in:
Rodin
2026-05-01 21:03:41 -07:00
parent b8af8306a6
commit 6a3c813279
2 changed files with 18 additions and 4 deletions
+17 -3
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"log"
"os"
"path/filepath"
"strconv"
"strings"
"time"
@@ -154,9 +155,22 @@ func main() {
// Step 6b: Load additional system prompt if specified
additionalPrompt := ""
if *systemPromptFile != "" {
data, err := os.ReadFile(*systemPromptFile)
workspace := os.Getenv("GITHUB_WORKSPACE")
if workspace == "" {
workspace, _ = os.Getwd()
}
absWorkspace, err := filepath.Abs(workspace)
if err != nil {
log.Fatalf("Failed to read system prompt file %q: %v", *systemPromptFile, err)
log.Fatalf("Failed to resolve workspace path: %v", err)
}
promptPath := filepath.Join(absWorkspace, *systemPromptFile)
promptPath = filepath.Clean(promptPath)
if !strings.HasPrefix(promptPath, absWorkspace+string(filepath.Separator)) && promptPath != absWorkspace {
log.Fatalf("system-prompt-file resolves outside workspace (got %q, workspace %q)", promptPath, absWorkspace)
}
data, err := os.ReadFile(promptPath)
if err != nil {
log.Fatalf("Failed to read system prompt file %q: %v", promptPath, err)
}
additionalPrompt = string(data)
log.Printf("Loaded system prompt file: %s (%d bytes)", *systemPromptFile, len(additionalPrompt))
@@ -227,7 +241,7 @@ func main() {
log.Printf("Warning: could not list existing reviews: %v", err)
} else {
for _, r := range reviews {
if r.ID != posted.ID && strings.Contains(r.Body, sentinel) {
if r.ID != posted.ID && r.User.Login == posted.User.Login && strings.Contains(r.Body, sentinel) {
if err := giteaClient.DeleteReview(ctx, owner, repoName, prNumber, r.ID); err != nil {
log.Printf("Warning: could not delete old review %d: %v", r.ID, err)
} else {