117 lines
9.1 KiB
JSON
117 lines
9.1 KiB
JSON
[
|
||
{
|
||
"location": "app/lib/gitea.js:28",
|
||
"role": "Assassin",
|
||
"original_finding": "Gitea API 請求在 headers 中直接放入了 `this.token`,若來源於不可信輸入且未經驗證,將導致 token 洩漏風險。",
|
||
"reason": "token 來自受信任的 `gitea.token`(CI 自動注入)而非使用者輸入;`_request` 從未將 headers 或 request 物件輸出到日誌,無實際洩漏路徑。錯誤訊息可能夾帶 token 的真正風險已於 index.js 頂層 catch 以 maskSecrets 遮蔽處理。"
|
||
},
|
||
{
|
||
"location": "app/lib/gitea.js:52",
|
||
"role": "Mage",
|
||
"original_finding": "findOpenPull 僅撈取前 50 個 PR,數量眾多可能導致重複建立;且 _request GET 未對回傳 json 結構嚴格驗證。",
|
||
"reason": "重複建立由 Gitea 在 POST 時回傳 422/409 阻擋,findOpenPull 僅在收到 422/409 後用於查回既有 PR 編號(fallback),分頁與否不影響是否重複建立。JSON 結構已透過 `if (!ok || !Array.isArray(json)) return null` 與 `_request` 的 try/catch 防禦驗證。"
|
||
},
|
||
{
|
||
"location": "app/lib/git.js:52",
|
||
"role": "Assassin",
|
||
"original_finding": "使用不可信的 remoteUrl 進行 fetch 操作存在 git 協定漏洞風險,建議驗證 remoteUrl 是否為預期 Gitea 網域。",
|
||
"reason": "remoteUrl 由 `${serverUrl}/${owner}/${repo}.git` 組成,serverUrl 來自受信任的 `gitea.server_url`(CI 環境變數),並非任意使用者輸入;且已使用 `--no-tags` 限制 refspec。容器基底為 node:20-bookworm-slim,git 版本為近期版本。"
|
||
},
|
||
{
|
||
"location": "app/lib/git.js:63",
|
||
"role": "Rogue",
|
||
"original_finding": "getCommitMessages 使用 `git log --max-count=50`,數量可能不足或過多。",
|
||
"reason": "50 筆為 PR 摘要的合理預設上限,非缺陷;改用 `--since` 屬使用場景偏好調整,無明確需求佐證,不在本次修復範圍。"
|
||
},
|
||
{
|
||
"location": "app/lib/util.js:14",
|
||
"role": "Rogue",
|
||
"original_finding": "run 函式 maxBuffer 設為 64MB,git diff 內容極大時易引發 OOM,建議改用 stream。",
|
||
"reason": "run() 採同步 spawnSync 為刻意設計(所有呼叫端皆同步取用 result.stdout);maxBuffer 為上限保護而非預先配置,僅在輸出達該量時才佔用;傳給 opencode 的 diff 已於 index.js 以 maxDiffChars 截斷。改為 stream 屬大規模架構重構,牽涉設計取捨。"
|
||
},
|
||
{
|
||
"location": "app/lib/git.js:39, 52",
|
||
"role": "Mage",
|
||
"original_finding": "多次使用 `git config --global` 修改全域設定,可能導致 ~/.gitconfig 無限膨脹、污染環境;safe.directory 使用萬用字元 `*` 過於寬鬆,建議改用 --local。",
|
||
"reason": "action 於每次執行皆在全新且即拋的 Docker 容器內運行,~/.gitconfig 不跨執行保留,無「無限膨脹」問題。safe.directory 基於安全考量 git 刻意忽略 repo-local 設定,必須寫在 global/system,無法改用 `--local`;在 owner 不可預期的 CI checkout 工作區使用 `*` 是 runner 的標準做法(如 actions/checkout 亦同)。user.name/email 已使用 --local。"
|
||
},
|
||
{
|
||
"location": "app/index.js:183",
|
||
"role": "Assassin",
|
||
"original_finding": "錯誤處理中的 maskSecrets 基於字串取代,可能無法處理所有 Token 變體導致敏感資訊洩漏;建議禁止輸出原始錯誤物件。",
|
||
"reason": "maskSecrets 以子字串比對取代,能涵蓋 token 出現於錯誤訊息的各處(含 URL 內嵌 `oauth2:<token>@`),實際洩漏向量(http.extraheader 帶入的原始 token)已被遮蔽。URL 編碼/base64 變體不會出現在本專案的錯誤路徑;完全禁止輸出 err.stack 會嚴重損及 CI 除錯能力,取捨上以遮蔽 token 為宜。"
|
||
},
|
||
{
|
||
"location": "app/index.js:7",
|
||
"role": "Leo",
|
||
"original_finding": "函式 main() 承擔過多責任,違反單一職責原則,建議抽離 ConflictManager 並封裝 Gitea API 互動。",
|
||
"reason": "屬主觀重構偏好而非缺陷;程式已分層為 Git/GiteaClient/OpenCode 三個職責清楚的類別,main() 僅負責編排流程,長度與複雜度可控,無立即重構必要。"
|
||
},
|
||
{
|
||
"location": "app/index.js:37",
|
||
"role": "Rogue",
|
||
"original_finding": "在 ahead 為 0 時,仍執行昂貴的 diff 採集與分析;建議先執行 countAheadCommits,若 ahead === 0 則直接終止。",
|
||
"reason": "現有程式已於 `countAheadCommits` 後立即檢查,`if (ahead === 0) { ...; return; }`(index.js:28-32)早於 diff 採集(index.js:36 起)就終止,與建議行為一致,屬誤報。"
|
||
},
|
||
{
|
||
"location": "app/lib/opencode.js:180",
|
||
"role": "Assassin",
|
||
"original_finding": "AI 模型產生的 PR 描述未經 sanitization,易遭 Prompt Injection 導致 Stored XSS 攻擊;建議在 extractResult 對 obj.description 使用 HTML Sanitizer。",
|
||
"reason": "description 以 Markdown 文字經 API 寫入 Gitea PR body,HTML 的消毒由 Gitea 渲染端負責(Gitea 對使用者內容套用 HTML sanitizer policy),非本 action 職責。description 是 Markdown 而非 HTML,在 client 端套用 HTML Sanitizer 反而會破壞合法的 Markdown 內容。"
|
||
},
|
||
{
|
||
"location": "app/lib/opencode.js:154",
|
||
"role": "Leo",
|
||
"original_finding": "summarize 函式使用 5 分鐘固定 timeout,大型 diff 可能導致分析失敗;建議改為可配置或依 diff 大小動態計算。",
|
||
"reason": "送入 opencode 的 diff 已於 index.js 以 maxDiffChars(60000 字元)截斷,prompt 大小有上限,5 分鐘對此規模輸入相當充裕;timeout 可配置屬增強而非缺陷。"
|
||
},
|
||
{
|
||
"location": "app/lib/opencode.js:127",
|
||
"role": "Mage",
|
||
"original_finding": "summarize 方法中使用 spawnSync 執行指令,未處理退出訊號可能導致清理競態。",
|
||
"reason": "spawnSync 為同步阻塞呼叫,回傳後才執行 finally 清理,無並行清理路徑,不存在競態;timeout/訊號終止時 spawnSync 仍會回傳,finally 的 rmSync 必定執行。"
|
||
},
|
||
{
|
||
"location": "app/lib/git.js:145",
|
||
"role": "Maya",
|
||
"original_finding": "合併衝突後未檢查是否存在殘留衝突標記;建議在 git add 後以 grep 掃描衝突標記。",
|
||
"reason": "createResolveBranch 刻意保留衝突標記並 commit,讓開發者在解衝突 PR 中看到並手動解決(PR body 亦明確要求解決 `<<<<<<<` 等標記),保留標記為設計核心;若在此偵測並失敗反而會破壞既定流程。"
|
||
},
|
||
{
|
||
"location": "app/lib/opencode.js:40",
|
||
"role": "Rogue",
|
||
"original_finding": "頻繁寫入讀取 opencode.json 設定檔造成無謂的 I/O;建議透過參數或環境變數傳入配置。",
|
||
"reason": "summarize 每次 action 執行僅呼叫一次,並非「頻繁」;opencode 以 OPENCODE_CONFIG 指向設定檔為其官方配置介面,寫入單一小檔的 I/O 可忽略。"
|
||
},
|
||
{
|
||
"location": "app/index.js:80",
|
||
"role": "Bard",
|
||
"original_finding": "分支命名格式若目標分支名稱過長,可能導致總長度超過 Git 限制;建議確保不超過 255 字元。",
|
||
"reason": "buildResolveBranchName 已將主體截斷至 MAX_BRANCH_STEM_LENGTH(180),連同前綴 `resolve-conflict/`(17)與 runId 後綴,總長度約 207,遠低於 Git 的 255 上限,已滿足建議。"
|
||
},
|
||
{
|
||
"location": "app/index.js:52",
|
||
"role": "Mage",
|
||
"original_finding": "opencode 失敗時,若相關資訊皆為空,fallback 機制產出的 PR 描述將空洞無效;建議檢查輸出內容或拋錯。",
|
||
"reason": "fallbackSummary 的 title 在無 commit 時退回 `Merge <source> into <target>`,description 恆包含固定結構標題(## 變更摘要、### Commits、### 變更檔案)與 `(無)` 佔位,不會產生空字串;PR 仍具基本可讀內容,非缺陷。"
|
||
},
|
||
{
|
||
"location": "app/lib/util.js:11, 13",
|
||
"role": "Bard",
|
||
"original_finding": "run 函式 Buffer 大小硬編碼,缺乏靈活性,且針對極端巨大輸入缺乏保護。",
|
||
"reason": "maxBuffer(64MB)為刻意的上限保護而非預先配置;本 action 於即拋容器內執行,將其抽為環境變數只增配置面而無實益。等同已收錄的 util.js:14 排除(同一機制)。"
|
||
},
|
||
{
|
||
"location": "app/index.js:176",
|
||
"role": "Bard",
|
||
"original_finding": "PR 已存在時僅記錄 log.info,CI 流程中可能需要更明確的提示;建議改用 log.warn 或 log.notice。",
|
||
"reason": "「PR 已存在」是冪等重跑下的正常且預期結果,log.info 語意正確;改為 warn 會在正常流程中產生誤導性警告雜訊,屬偏好而非缺陷。"
|
||
},
|
||
{
|
||
"location": "app/lib/git.js:32",
|
||
"role": "Leo",
|
||
"original_finding": "Sensitive Token 處理耦合在 Git 類別中,且未驗證有效性;建議將遮蔽邏輯交由 util.js 或於初始化時驗證。",
|
||
"reason": "token 遮蔽邏輯已實作於 util.js 的 maskSecrets 並由 Git 類別重用(非重複實作);token 存在性已於 inputs.js 的 required('GITEA_TOKEN') 驗證。Git 持有 token 以組 http.extraheader 為必要,耦合度可接受。"
|
||
}
|
||
]
|