chore(ai-review 狀態): 更新 findings 與 exclusions
CI / 1. BUILD (pull_request) Successful in 2s
CI / 2. TEST (pull_request) Successful in 7m24s
CI / 3. RESULT (pull_request) Successful in 1s

This commit is contained in:
2026-07-11 14:00:55 +00:00
parent bfeea4c2a9
commit 98abcf2363
2 changed files with 65 additions and 48 deletions
+65
View File
@@ -63,5 +63,70 @@
"reason": "專案目前沒有測試基礎設施,先將核心邏輯修正並保留此項為後續技術債。",
"source": "develop...ai-review-resolve/develop-20260711-131608",
"date": "2026-07-11"
},
{
"key": "src/index.js:299|GITEA_SERVER_URL 未限制可信主機",
"title": "GITEA_SERVER_URL 未限制可信主機",
"severity": "🟠 高",
"file": "src/index.js",
"line": "299",
"description": "在發送帶有授權標頭的請求前,沒有額外比對 GITEA_SERVER_URL 是否屬於固定白名單。",
"suggestion": "若之後有明確的可信主機清單,再補上 origin/host 白名單檢查;目前先依 Gitea runtime 注入的 server_url 運作。",
"verdict": "誤判",
"reason": "這個 action 只會在 Gitea runtime 提供的 `gitea.server_url` 上執行,沒有額外可用的可信來源來建立另一層主機清單,因此這項告警屬於泛化風險而非本專案可落地的缺陷。",
"source": "develop...ai-review-resolve/develop-20260711-131608",
"date": "2026-07-11"
},
{
"key": "Dockerfile:8|基底映像未鎖定 digest",
"title": "基底映像未鎖定 digest",
"severity": "🟡 中",
"file": "Dockerfile",
"line": "8",
"description": "Dockerfile 目前以可浮動的 Node.js 標籤作為基底映像。",
"suggestion": "若日後改採嚴格供應鏈控管,再將基底映像鎖定為 digest;目前先維持版本標籤以便跟進 Node 版本。",
"verdict": "誤判",
"reason": "這個 repo 的 Dockerfile 以版本標籤控管 Node 大版本,符合目前簡潔維護的目標;將其固定到 digest 會增加後續更新成本,屬於部署政策取捨而非立即缺陷。",
"source": "develop...ai-review-resolve/develop-20260711-131608",
"date": "2026-07-11"
},
{
"key": "src/index.js:1|檔案責任切分過於集中",
"title": "檔案責任切分過於集中",
"severity": "🟡 中",
"file": "src/index.js",
"line": "1",
"description": "單一檔案同時承擔 logger、驗證、HTTP client 與清理流程。",
"suggestion": "若之後擴充出更大的功能,再考慮拆分成獨立模組。",
"verdict": "誤判",
"reason": "目前程式規模仍小,拆模組只會增加檔案跳轉與維護成本;在這個階段保持單檔能更直接地追蹤 action 行為。",
"source": "develop...ai-review-resolve/develop-20260711-131608",
"date": "2026-07-11"
},
{
"key": "src/index.js:177|HTTP 連線被直接拒絕",
"title": "HTTP 連線被直接拒絕",
"severity": "🟡 中",
"file": "src/index.js",
"line": "177",
"description": "request helper 只允許 HTTPS,遇到 HTTP 端點會直接失敗。",
"suggestion": "若之後需要支援 HTTP 自架環境,再把協定限制做成可配置;目前先維持 HTTPS-only。",
"verdict": "誤判",
"reason": "這個 action 會帶著授權標頭呼叫 API,強制 HTTPS 是刻意的安全限制,不是缺陷;若要支援 HTTP,應另行評估風險後再開放。",
"source": "develop...ai-review-resolve/develop-20260711-131608",
"date": "2026-07-11"
},
{
"key": "src/index.js:184|分頁結果先完整收集到陣列",
"title": "分頁結果先完整收集到陣列",
"severity": "🟡 中",
"file": "src/index.js",
"line": "184",
"description": "fetchAllPages 會把所有頁面合併到單一陣列後再交給後續流程。",
"suggestion": "若未來資料量大幅成長,再考慮改成串流處理或分段消耗。",
"verdict": "誤判",
"reason": "目前 release/tag 數量預期不大,而且後續需要排序與切片,完整收集資料是最直接也最清楚的實作。",
"source": "develop...ai-review-resolve/develop-20260711-131608",
"date": "2026-07-11"
}
]
-48
View File
@@ -1,12 +1,4 @@
[
{
"level": "critical",
"role": "Mage",
"problem": "這裡在 DELETE 回傳非 204 時只寫錯誤訊息,沒有把失敗往上拋或標記成整體失敗;同樣的寫法在後面的 tag 刪除區塊也出現一次。最小重現:只要某個 release 因權限不足回 403,step 仍會繼續跑完並以成功結束,外層 workflow 會誤判清理已完成。",
"suggestion": "把刪除結果納入整體失敗狀態,例如遇到非 204 直接 `throw`,或累積 `hadFailure` 後在流程結束時 `process.exit(1)`,不要讓任何刪除失敗被靜默吞掉。",
"location": "src/index.js:302",
"is_new": false
},
{
"level": "critical",
"role": "Assassin",
@@ -15,30 +7,6 @@
"suggestion": "不要只驗證協定,必須把目標主機固定在預期的 Gitea 來源;改成解析 `URL` 後比對 `origin`/host 白名單,拒絕任何非預期網域,並且只在確認是可信任的 Gitea 站台時才附加 `Authorization` header。",
"is_new": true
},
{
"level": "warning",
"role": "Mage",
"problem": "這裡先抓一份 release 快照,再在後面依這份快照去刪 tag;兩個步驟之間不是同一個時間點。最小重現:cleanup 跑到一半時剛好有人新增 release,新 release 的 tag 來不及出現在 `releaseTags`,接下來的 tag 清理就可能把剛發布的 tag 誤刪。",
"suggestion": "把 release 與 tag 的判定建立在同一個一致性快照上,或在刪 tag 前重新驗證該 tag 目前是否已被任何 release 使用;如果環境允許,最好加上流程鎖避免與發版同時執行。",
"location": "src/index.js:312",
"is_new": false
},
{
"level": "warning",
"role": "Rogue",
"problem": "這裡又對 releases API 做一次完整 `fetchAllPages()`,前面第 267 行已經抓過同一份資料並排序;等於把整個分頁抓取、JSON 解析與記憶體配置再跑一遍,資料量越大越浪費。",
"suggestion": "直接沿用前一次抓到的 `releaseJson`,或先從第一次結果算出要保留的 tag 集合,避免第二次全量拉取。",
"location": "src/index.js:312",
"is_new": false
},
{
"level": "warning",
"role": "Rogue",
"problem": "tag 刪除同樣是逐筆 `await`,當 tag 數量多時會把每次 API 往返都串成排隊,刪除時間幾乎全卡在網路延遲上。",
"suggestion": "用受限並行處理 tag 刪除,或先收集待刪清單再批次送出,減少總等待時間。",
"location": "src/index.js:326",
"is_new": false
},
{
"level": "warning",
"role": "Assassin",
@@ -63,22 +31,6 @@
"suggestion": "若這個 action 需要支援常見的自架環境,應移除固定只允許 HTTPS 的限制,或把協定限制做成可配置;若確實只支援 HTTPS,也要在 action 說明中明確標示,避免使用者在 `http` 環境下直接踩雷。",
"is_new": true
},
{
"level": "warning",
"role": "Mage",
"location": "src/index.js:353",
"problem": "前面只要有任何 release 刪除失敗,這裡仍然會繼續做 tag 清理,而且 `releaseTags` 是依照刪除前的清單算出來的。最小重現情境是某個待刪 release 因權限不足或暫時性網路錯誤沒刪掉,接著它對應的 tag 仍可能被刪除,最後變成 release 還在、tag 卻被移除的半套狀態。",
"suggestion": "在進入 tag 清理前先檢查 release 刪除是否有失敗;只要有失敗就應中止後續 tag 刪除,或改成只把實際成功刪除的 release 對應 tag 納入待刪集合,避免留下不一致狀態。",
"is_new": true
},
{
"level": "warning",
"role": "Rogue",
"location": "src/index.js:25",
"problem": "每次輸出一條 log 都要跑 `Intl.DateTimeFormat.formatToParts()`,還額外建立 `lookup` 物件再組字串;這條熱路徑會在每個 release、tag 與錯誤訊息上重複消耗 CPU,訊息一多就很浪費。",
"suggestion": "把時間格式改成可快取的字串產生方式,例如同一秒共用結果,或改用較便宜的 formatter,不要每條 log 都做 `formatToParts()` 拆解。",
"is_new": true
},
{
"level": "warning",
"role": "Rogue",