[ { "location": "app/index.js:15", "role": "Bard", "original_finding": "此函式註解過於詳盡描述執行流程(如 logger.fail、writeOutput),應專注於描述函式功能而非具體實作步驟。", "reason": "詳述行為的 JSDoc 為本專案 doc-funcs 文件慣例,全模組一致採用;main 的 JSDoc 另需說明可注入的 deps 參數,刻意保留必要細節。" }, { "location": "app/releases.js:49", "role": "Rogue", "original_finding": "浪費 CPU 週期在手動處理 JSON 解析。response.text() 再 JSON.parse() 的效能比 response.json() 慢得多。建議直接使用 await response.json()。", "reason": "text()+JSON.parse 為刻意設計:需先以字串判斷空 body 或字面 'null' 以決定分頁是否結束,改用 response.json() 會在空回應時拋錯而破壞分頁終止邏輯。" }, { "location": "app/version.js:128", "role": "Rogue", "original_finding": "重複遍歷資料!在 calculateVersion 中先呼叫 latestStableVersion 遍歷一次,隨後又呼叫 nextBetaNumber 再遍歷一次。建議先解析並篩選一次再傳遞給後續函式。", "reason": "latestStableVersion 篩選的是穩定版、nextBetaNumber 篩選的是對應 beta 標籤,兩者為不同子集無法共用單次解析;且 release 為分頁取得的小資料集,效益可忽略,現行設計以可組合的純函式換取可讀性。" }, { "location": "app/version.js:77", "role": "Bard", "original_finding": "String(latest) 呼叫顯得冗贅,因為 latest 在此處已明確為字串型別。建議直接使用 latest.split('.')。", "reason": "nextReleaseVersion 為對外公開(exported)函式,String() 為防禦性處理,確保被直接以非字串呼叫時也不致拋錯。" }, { "location": "Dockerfile:13", "role": "Assassin", "original_finding": "移除 `--no-check-certificate`。若確實有無法解決的憑證問題,應排查來源網域的信任鏈或安裝正確的憑證,而不是直接關閉安全機制。", "reason": "AI 對話收斂判定為誤報(問題在最新程式碼中不成立或不適用)" }, { "location": "app/index.js:41", "role": "Assassin", "original_finding": "Action 未對 GITEA_SERVER_URL 進行格式驗證,攻擊者若能控制 CI/CD 環境變數,即可將該值設定為惡意 URL,導致 GITEA_TOKEN 外洩。建議嚴格驗證格式並符合網域白名單。", "reason": "GITEA_SERVER_URL 由 Gitea Actions 平台注入(gitea.server_url),非一般威脅模型下使用者可控;loadConfig 已加入 http/https URL 格式驗證;網域白名單屬各部署環境特定決策,不宜硬寫進通用 action。" }, { "location": "app/index.js:18", "role": "Maya", "original_finding": "主邏輯函式 main 處理了 loadConfig 與 fetchReleases 的例外情境,但缺乏針對這些失敗路徑的整合測試。", "reason": "前提已不成立:test/index.test.js 已以相依注入新增 main 成功路徑,以及 loadConfig 失敗、fetchReleases 失敗兩條失敗路徑的整合測試。" }, { "location": "app/output.js:16", "role": "Assassin", "original_finding": "writeOutput 直接接收 file 路徑並 fs.appendFileSync 寫入,預設來源為 GITHUB_OUTPUT,存在任意檔案寫入/路徑穿越風險。建議對路徑加入嚴格驗證。", "reason": "GITHUB_OUTPUT 由 Action runner 注入並指向授權的暫存輸出檔,寫入它正是回傳 step output 的標準機制;對通用 action 而言硬性限制路徑會破壞功能,且該變數於正常威脅模型中非使用者可控。" }, { "location": "app/version.js:4", "role": "Leo", "original_finding": "版本號區段的進位上限(10)被直接硬編碼在程式中,未來調整進位規則需深入核心修改。建議設為配置常數或參數化。", "reason": "進位上限已抽出為模組頂層具名常數 SEGMENT_LIMIT,可單點調整;進位規則為本 action 固定的業務規則,參數化屬尚無需求的過度設計。" }, { "location": "app/logger.js:4", "role": "Leo", "original_finding": "日誌分隔線寬度與符號直接硬編碼在模組內,調整風格需改多處。建議集中管理並提供通用產生函數。", "reason": "分隔線已是模組頂層集中定義的常數 LINE/SUBLINE,單點即可調整;為固定的視覺樣式再加產生函數屬過度設計。" }, { "location": "app/test/releases.test.js:10", "role": "Leo", "original_finding": "withFetch 為全域 fetch 的通用封裝工具,目前定義在特定測試檔案內。建議提取至獨立的測試工具檔案(例如 app/test/test-utils.js)以提升重用性。", "reason": "目前僅 releases.test.js 單一測試檔使用 withFetch(logger.test.js 使用的是不同的 stdout/stderr 攔截輔助),尚無第二個消費者;為單一用途提前抽出共用模組屬過度設計。" }, { "location": "app/test/logger.test.js:8", "role": "Leo", "original_finding": "在測試中使用 monkey-patch 直接覆蓋 process.stdout.write 或 process.stderr.write 是極度危險的模式,可能導致狀態污染;建議重構 logger 使其支援依賴注入。", "reason": "攔截已於 finally 還原原本的 write,無狀態污染,且為 Node 測試 stdout/stderr 輸出的標準作法;logger 僅是寫入 stdout/stderr 的薄封裝,為其引入依賴注入框架屬過度設計。已將兩個攔截輔助合併為單一 captureStream。" }, { "location": "app/config.js:63", "role": "Mage", "original_finding": "正規表達式 ^[A-Za-z0-9._-]+$ 仍允許以點號開頭或結尾的名稱(如 .foo 或 foo.)。建議調整為點號只能存在於中間。", "reason": "路徑穿越風險來自 .、.. 與額外斜線,皆已明確排除;前/後綴點號非穿越向量,且禁止會誤拒如 .github 這類合法 repo 名稱。" }, { "location": "app/test/config.test.js:65", "role": "Bard", "original_finding": "for...of 迴圈測試將多種錯誤案例綁在同一個測試名稱下,失敗時難以辨識是哪一種格式。建議拆分或加入描述性訊息。", "reason": "迴圈內 assert.throws 已帶入第三引數描述訊息(應拒絕:),失敗時可定位具體案例;逐案拆成獨立 test 屬純風格偏好。" }, { "location": "app/config.js:62", "role": "Mage", "original_finding": "parts.every 僅檢查單一區段長度,未對 owner/repo 總長度做限制。建議分割前先限制 value 總長度。", "reason": "已限定恰兩段且每段 <= MAX_REPO_NAME_LENGTH,總長度已被間接上限;再加總長度檢查為冗餘。" }, { "location": "app/releases.js:68", "role": "Assassin", "original_finding": "將未經清洗的 API 回應片段納入 Error,若 API 返回敏感資訊可能導致外洩。建議僅含概括描述或先脫敏。", "reason": "此片段為前一輪審查明確要求加入以利除錯;release 清單 API 的非 JSON 回應通常為錯誤頁/代理訊息而非機密資料,且片段已截斷。兩輪建議互相衝突,維持可偵錯性。" }, { "location": "app/test/releases.test.js:33", "role": "Bard", "original_finding": "jsonResponse 輔助函式定義在測試檔內,建議統一抽離至 app/test/support/mock.js 集中管理。", "reason": "目前僅 releases.test.js 單一測試檔使用,「若未來」屬臆測性需求,為單一消費者提前抽出共用模組屬過度設計。" }, { "location": "app/config.js:65", "role": "Rogue", "original_finding": "將 Regex 移至函數外層宣告為常數。", "reason": "AI 對話收斂判定為誤報(問題在最新程式碼中不成立或不適用)" } ]