Files
release-cleanup/.gitea/ai-review/findings.json
T
JefferyandClaude Opus 4.8 7b742ed85e
CI / AI Code Review (pull_request) Failing after 50s
chore(ai-review): 更新 findings.json 與 exclusions.json
移除本輪已修復(server URL 正規化、id 整數驗證、整合測試)與重複提報的 finding;
保留 7 條設計取捨(重試/錯誤處理/DoS/TOCTOU/deleteResource 策略);
新增 3 條不適用至 exclusions(baseUrl 由已驗證 config 組成、tag 白名單非必要、
categorizeTags 拆分無益)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 13:55:48 +08:00

66 lines
4.3 KiB
JSON

[
{
"level": "warning",
"role": "Mage",
"location": "app/releases.js:38",
"problem": "清理流程對網路請求依賴強,若 API 呼叫失敗,整個 main 流程中斷,無法確保後續清理的一致性與部分成功重試。",
"suggestion": "引入更細緻的錯誤處理(如錯誤閾值機制)或部分清理成功後的重試策略。",
"status": "deferred",
"defer_reason": "錯誤處理/重試策略的設計取捨。目前單筆刪除失敗會記錄並繼續、讀取失敗則中止屬合理保守行為;是否引入閾值/重試保留待人工評估。"
},
{
"level": "warning",
"role": "Maya",
"location": "app/releases.js:46",
"problem": "cleanupReleases 中若 fetchAllPages 拋錯,cleanupOrphanTags 不會執行;缺乏部分失敗後的清理與回報機制。",
"suggestion": "考慮在 cleanupReleases 加入 try/catch,僅該步驟失敗時記錄並仍嘗試 cleanupOrphanTags,或明確標示部分清理狀態。",
"status": "deferred",
"defer_reason": "目前採 fail-fast:無法取得 release 清單時不應依過時資料刪除 tag,中止較安全;且 fetchAllPages 的錯誤訊息已含失敗的 GET URL,可辨識中斷步驟。是否改為跨步驟續行屬設計取捨,保留待人工評估。"
},
{
"level": "warning",
"role": "Assassin",
"location": "app/gitea-client.js:66",
"problem": "錯誤路徑以 res.text() 讀取整個回應主體,未限制大小,惡意伺服器可回傳極大內容導致記憶體耗盡(DoS)。",
"suggestion": "限制讀取的回應大小,例如檢查 Content-Length 或以串流方式設定讀取上限。",
"status": "deferred",
"defer_reason": "風險低:目標為已通過 URL 驗證的受信任 Gitea 實例,且每請求已有 30 秒逾時。正確修法需串流逐段讀取並設位元組上限,屬較大改動,保留待人工評估。"
},
{
"level": "warning",
"role": "Assassin",
"location": "app/gitea-client.js:77",
"problem": "成功路徑以 res.json() 解析整個回應,未限制大小,惡意伺服器可回傳極大 JSON 導致記憶體耗盡(DoS)。",
"suggestion": "對 API 回應設定明確大小上限,超過時拒絕解析並拋出異常。",
"status": "deferred",
"defer_reason": "與 app/gitea-client.js:66 同類:受信任目標、已有逾時與 MAX_PAGES 約束,風險低;正確修法需串流讀取並設上限,屬較大改動,保留待人工評估。"
},
{
"level": "warning",
"role": "Assassin",
"location": "app/gitea-client.js:106",
"problem": "將 items 直接放入 all 陣列,若 API 回傳異常巨大的 JSON 陣列,可能導致容器記憶體耗盡(DoS)。",
"suggestion": "增加最大總項目數限制,並考慮以 AsyncGenerator 串流式處理降低記憶體佔用。",
"status": "deferred",
"defer_reason": "總量已受 MAX_PAGES(1000 頁)間接約束;改為 AsyncGenerator 串流處理屬較大架構改動,對 release/tag 數量有限的清理任務效益不高,保留待人工評估。"
},
{
"level": "warning",
"role": "Mage",
"location": "app/tags.js:46",
"problem": "cleanupOrphanTags 分兩次 API 呼叫取得 releases 與 tags,兩次之間若 Gitea 狀態變更,categorizeTags 可能基於不一致狀態而誤刪。",
"suggestion": "考量原子性需求,或至少在日誌標示兩次取得資料的時間間距以利除錯。",
"status": "deferred",
"defer_reason": "Gitea API 無交易機制;現行已在 cleanupOrphanTags 開頭重新抓取最新 release 作為主要緩解,殘餘競態窗極小且屬排程任務可接受範圍。是否再加每筆刪除前複查屬一致性/成本取捨,保留待人工評估。"
},
{
"level": "warning",
"role": "Maya",
"location": "app/gitea-client.js:115",
"problem": "deleteResource 僅回傳狀態碼,對於 401/403/404 等錯誤未做區分處理,呼叫方策略較鬆散。",
"suggestion": "在 deleteResource 內針對常見錯誤碼拋出更有意義的例外,讓呼叫方可採取跳過/重試/中止等對應策略。",
"status": "deferred",
"defer_reason": "現行刻意讓 deleteResource 單純回傳狀態碼、由呼叫端記錄 HTTP code 後續行;依狀態碼採取不同策略(如遇 401 中止)與重試/閾值同屬錯誤處理設計取捨,與 app/releases.js:38 一併保留待人工評估。"
}
]