[ { "level": "critical", "role": "Mage", "location": "src/index.js:400", "problem": "這裡在刪除 tag 的流程中只把失敗記進 `hadFailure`,但流程結束後沒有再檢查或拋錯。最小重現:只要任一個 tag 刪除回傳 404/500,程式仍會以 0 結束,外層 CI 會誤判為清理成功,但實際上遺留的 tag 還在。", "suggestion": "在 `processInBatches(tagJson, ...)` 結束後補上 `if (hadFailure) throw new Error(...)`,讓任何 tag 刪除失敗都會正確回傳非 0 狀態。", "is_new": true }, { "level": "warning", "role": "Assassin", "location": "src/index.js:155", "problem": "這裡把 `GITEA_SERVER_URL` 原樣寫進 log,若 URL 內含 userinfo、查詢字串或被惡意塞入敏感資訊,這些內容會直接落到 action log,形成可被讀取的資料外洩點。", "suggestion": "不要記錄完整 URL;只輸出必要的非敏感資訊,例如遮罩後的主機名,或改成只記錄是否存在。", "is_new": true }, { "level": "warning", "role": "Assassin", "location": "src/index.js:345", "problem": "`releaseItem.id` 直接進入 DELETE URL,完全信任 API 回來的值;如果回應被污染或伺服器回傳惡意資料,攻擊者就能把刪除請求導向非預期路徑。", "suggestion": "在組 URL 前先確認 `id` 一定是正整數,拒絕任何非數字或異常範圍的值,再送出刪除請求。", "is_new": true }, { "level": "warning", "role": "Mage", "location": "src/index.js:144", "problem": "這個空值判斷把字串 `'null'` 也當成空值。最小重現:若某個 release 的 `tag_name` 真的就是 `null`,它會在 `releaseTags` 建立時被排除,後續 tag 清理會把這個原本應保留的 tag 誤刪。", "suggestion": "不要在通用空值判斷裡把字串 `'null'` 視為空值;只保留 `undefined`、`null` 與空字串。如果某些輸入來源真的會傳出字面值 `'null'`,請在那個來源各自做正規化。", "is_new": true }, { "level": "warning", "role": "Rogue", "location": "src/index.js:183", "problem": "這裡每次 request 都重新走一次預設 HTTPS 連線,沒有重用 keep-alive 連線。後面又會連續打多次頁面查詢與刪除 API,TLS 握手和 socket 建立會被重複支付,release/tag 數量一多就很浪費延遲與 CPU。", "suggestion": "改成共用 `https.Agent({ keepAlive: true })`,並把同一個 agent 傳給所有 GET/DELETE request,減少重複建連線的成本。", "is_new": true }, { "level": "info", "role": "Assassin", "location": "src/index.js:228", "problem": "分頁迴圈沒有上限,只要對方持續回傳非空頁面,這個 action 就會無限抓取;惡意或故障中的 API 可以把 runner 卡死,消耗時間與配額。", "suggestion": "加入最大頁數、重複頁檢測或總筆數上限,超過就中止並回報異常,避免被外部回應拖成無限迴圈。", "is_new": true }, { "level": "info", "role": "Bard", "location": "src/index.js:337", "problem": "批次大小直接裸寫 `4`,而且在後面同樣又出現一次;這種數字沒有名字,像臨時即興的節拍,之後要調整時很難一眼找到所有節點。", "suggestion": "把批次大小抽成具名常數,例如 `const DELETE_CONCURRENCY = 4;`,兩個呼叫點共用,畫面會更整齊,也更好維護。", "is_new": true }, { "level": "info", "role": "Leo", "location": "src/index.js:409", "problem": "在 `catch` 裡先把 `currentStage` 清空再記錄錯誤,會讓最後那筆失敗 log 失去「到底是在哪個階段炸掉」的上下文。等到未來有人要追問題時,只能回頭翻前面的輸出,比對成本會很高。", "suggestion": "保留最後的 `currentStage`,或在進入 `catch` 時把階段一起寫進錯誤訊息;如果擔心汙染後續輸出,可以在輸出完成後再重設,而不是先清空。", "is_new": true } ]