Files
codex/.gitea/ai-review/exclusions.json
T
jiantw83 82d8a8ed04
CI / 計算版本號 (pull_request) Successful in 2s
CI / 工具測試 (pull_request) Successful in 7s
AI / Code Review (pull_request) Successful in 38s
chore(ai-review 狀態): 清除已處理 findings
2026-06-24 14:05:53 +00:00

153 lines
12 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
[
{
"location": "action.yaml:23",
"role": "Assassin",
"original_finding": "將包含認證資訊的 `OAUTH` 透過環境變數傳遞,這使得該敏感資訊在容器內的任何進程皆可透過環境變數(如 `/proc/self/environ`)輕易竊取。",
"reason": "此 action 透過 Gitea/GitHub Docker Action input 接收 secretaction metadata 只能將 input 映射為容器環境變數;呼叫端仍使用 secrets.CODEX_OAUTH,未在 workflow 明文暴露。"
},
{
"location": "entrypoint.sh:18",
"role": "Assassin",
"original_finding": "雖然有 `chmod 600`,但 `auth.json` 放在 `/root/.codex/` 目錄下,若發生容器逃逸,該敏感金鑰極易被讀取。",
"reason": "Codex CLI 目前需要讀取 CODEX_HOME/auth.json;容器內已限制為 600 權限,外部 Secret Store 掛載不是此 Docker Action 目前可控制的介面。"
},
{
"location": "action.yaml:6",
"role": "Leo",
"original_finding": "將 Base64 編碼的認證資訊設為 Action input,導致明文暴露在 Workflow 配置中,難以維護。",
"reason": "workflow 傳入的是 secrets.CODEX_OAUTH,不是明文值;使用 input 是 Docker Action 接收呼叫端 secret 的標準介面。"
},
{
"location": "entrypoint.sh:22",
"role": "Rogue",
"original_finding": "在腳本中頻繁進行 I/O 操作(重複寫入 auth.json),缺乏快取檢查。",
"reason": "每次 Docker Action 執行都是短生命週期容器,auth.json 需要從當次 secret 重建;快取檢查不會降低跨執行 I/O,也可能增加 secret 狀態判斷複雜度。"
},
{
"location": "action.yaml:4",
"role": "Bard",
"original_finding": "輸入參數 `oauth` 實質為 base64 編碼的 json,命名易生誤解。",
"reason": "此 action 已對外發布並由既有 workflow 使用 oauth input;直接更名會造成破壞性變更,先保留相容介面與描述文字。"
},
{
"location": "Dockerfile:4",
"role": "Rogue",
"original_finding": "在 Dockerfile 中安裝了 git 且未清理,導致映像檔過大。",
"reason": "Codex CLI 與 plugin 安裝/執行流程可能需要 git 支援;為避免 runtime 缺少 git 造成 action 失敗,目前保留 git。"
},
{
"location": "Dockerfile:25",
"role": "Rogue",
"original_finding": "插件安裝指令採取連續序列執行,導致多次獨立的網路 I/O 等待,嚴重浪費建置時間。",
"reason": "codex plugin 指令會修改同一份本機 plugin 狀態,並行安裝可能造成狀態競爭;目前保留循序安裝以確保可預測性。"
},
{
"location": "entrypoint.sh:22",
"role": "Leo",
"original_finding": "直接使用 `mktemp` 在 `CODEX_HOME` 目錄下建立臨時檔案,且 `CODEX_HOME` 若未正確隔離,在多個 Action 同時執行時可能會導致檔案名稱衝突。",
"reason": "Docker Action 每次執行都有獨立容器與 CODEX_HOME;mktemp 也會建立隨機檔名,實務上不會跨 action 執行衝突。"
},
{
"location": "entrypoint.sh:16",
"role": "Leo",
"original_finding": "硬編碼了預設路徑 `/root/.codex`,這使得映像檔的可移植性受限,且如果在非 root 使用者環境下執行此容器,可能會因為權限問題而失敗。",
"reason": "Dockerfile 明確以 root 環境執行並設定 CODEX_HOME=/root/.codexentrypoint 仍允許呼叫端用 CODEX_HOME 覆寫預設路徑。"
},
{
"location": "entrypoint.sh:6",
"role": "Maya",
"original_finding": "應在測試案例中模擬空 OAUTH 輸入,並驗證腳本是否正確拋出錯誤並以 exit 1 終止。",
"reason": "AI 對話收斂判定為誤報(問題在最新程式碼中不成立或不適用)"
},
{
"location": "entrypoint.sh:11",
"role": "Maya",
"original_finding": "應在測試案例中模擬空 MODEL 輸入,並驗證腳本是否正確拋出錯誤並以 exit 1 終止。",
"reason": "AI 對話收斂判定為誤報(問題在最新程式碼中不成立或不適用)"
},
{
"location": "Dockerfile:17",
"role": "Bard",
"original_finding": "將安裝腳本邏輯直接寫在 `RUN` 指令中顯得冗長,且使用 `$(mktemp)` 容易產生難以追蹤的臨時檔案。",
"reason": "安裝流程需在同一 Docker layer 中下載、驗證 SHA-256、執行並清理暫存腳本;留在 Dockerfile 可讓供應鏈驗證步驟與安裝命令緊鄰,mktemp 產生的檔案也已於同一 RUN 中刪除。"
},
{
"location": "entrypoint.sh:45",
"role": "Bard",
"original_finding": "使用靜態路徑檢查 `auth.json` 是否存在,若前次執行中斷導致檔案未清除,會導致後續執行失敗(Self-inflicted DoS)。",
"reason": "拒絕覆寫既有 auth.json 是刻意的 secret 安全保護,避免覆蓋呼叫端掛載或殘留的認證檔;Docker Action 預期每次執行使用獨立容器,前次中斷造成殘留的風險低於靜默覆寫 secret 的風險。"
},
{
"location": "tests/entrypoint_test.sh:17",
"role": "Bard",
"original_finding": "在測試中建立 `codex` 指令時,Here-document 與命令混雜,可讀性較低。",
"reason": "測試 helper 需要動態產生可執行的假 codex 指令,here-document 在此處比額外 fixture 檔更直觀且維持測試自含;此項屬風格偏好,不影響行為正確性。"
},
{
"location": "Dockerfile:10",
"role": "Assassin",
"original_finding": "Codex 外掛市集來源指向 `gitea.jsc.idv.tw`,未驗證來源的安全性。若該伺服器遭駭,將導致自動安裝惡意或篡改過的外掛,進而導致供應鏈攻擊。",
"reason": "Dockerfile 已使用 `codex plugin marketplace add --ref` 將 doc 與 code-review marketplace 固定到指定 commit SHA;此 action 需要安裝內部 Gitea marketplace 外掛,來源伺服器信任與存取控管屬部署環境治理,不適合在 Dockerfile 內改成其他來源。"
},
{
"location": "Dockerfile:24",
"role": "Leo",
"original_finding": "插件 URL 與版本參照 (REF) 硬編碼在 Dockerfile 中,未來若需更新插件或更換來源,需重新編譯整個 Docker 映像檔,維護成本較高。",
"reason": "此 Docker Action 需要可重現的建置結果;將 marketplace URL 與 ref 固定在 Dockerfile ARG 中,可讓外掛版本變更必須經由映像檔重建與 code review,避免外部設定在執行時靜默改變供應鏈內容。"
},
{
"location": "tests/entrypoint_test.sh:65",
"role": "Maya",
"original_finding": "測試案例對於輸入參數的邊界測試(例如 `PROMPT` 為空字串、極長字串)不足。",
"reason": "目前測試已包含 `test_empty_prompt` 與 `test_prompt_with_shell_characters`,覆蓋空字串與含 shell 特殊字元的 PROMPT 傳遞;此 finding 對最新測試內容已不成立。"
},
{
"location": "entrypoint.sh:49",
"role": "Mage",
"original_finding": "在執行 install -m 600 時,若 codex 進程已經在嘗試讀取 auth.json,會發生檔案存取競態(Race Condition)。雖然使用了 flock,但這僅在同一個 shell 腳本實例中有效,無法保護跨容器或跨執行環境的檔案存取一致性。",
"reason": "最新入口已改為 `entrypoint.sh` 呼叫 `app/main.js`,不存在 `install -m 600`Node.js 實作會先寫入並 chmod auth.json 後才啟動 codex,且 Docker Action 每次執行為獨立容器,跨容器不共享 CODEX_HOME。"
},
{
"location": "entrypoint.sh:58",
"role": "Mage",
"original_finding": "在容器化環境(通常是 ephemeral 的)中,auth.json 寫入後立刻被刪除,這會導致 codex 在後續執行中因找不到驗證檔案而無法運作。另外,trap 的清理機制會導致該檔案在 codex 完成工作前被刪除,這對於長效執行或需要多次存取的應用場景是錯誤的設計。",
"reason": "最新 Node.js 實作會等待 `codex exec` 子程序結束並寫入 output 後才執行 cleanupauth.json 在 codex 執行期間持續存在,不會在工作完成前被刪除。"
},
{
"location": "Dockerfile:32",
"role": "Mage",
"original_finding": "在 Dockerfile 中直接使用 RUN 來下載並執行安裝腳本,沒有進行網路連接穩定性的驗證或完整的錯誤恢復機制。一旦網路不穩導致腳本不完整,後續的 sha256sum 檢查會失敗,但 Dockerfile 層疊技術可能會導致中間層殘留損壞的檔案。",
"reason": "Dockerfile 已在同一個 RUN 中完成下載、SHA-256 驗證與安裝,並使用 `curl --retry 3 --retry-delay 2 --max-time 120`checksum 失敗會使該 layer 建置失敗,不會產生可用的損壞中間成果。"
},
{
"location": "app/main.js:106",
"role": "Assassin",
"original_finding": "在執行 `codex` 子行程時,使用了 `--dangerously-bypass-approvals-and-sandbox` 參數。這會完全繞過沙盒機制與審核流程,如果 `prompt` 內容受到攻擊者控制,該 CLI 工具將獲得在容器中執行任意代碼的權限。",
"reason": "此 action 的用途是在隔離的短生命週期 CI 容器中代替使用者執行 Codex,必須允許 Codex 非互動式修改 workspaceworkflow 呼叫端需以 trusted prompt/secret 使用,本次已在 `runCodex` 前加入註解明確標示此安全取捨。"
},
{
"location": "app/main.js:143",
"role": "Assassin",
"original_finding": "將 `OAUTH` 環境變數內容解碼並直接寫入 `auth.json`。雖然有檢查 base64 格式與 JSON 結構,但若解碼後的 JSON 內容包含惡意配置(如惡意插件路徑或偽造的 API 憑證),可能導致後續 `codex` CLI 在執行時被劫持或洩漏資料。",
"reason": "`OAUTH` 是呼叫端提供給 Codex CLI 的 auth.json secretaction 只能驗證 base64、JSON object 與檔案權限,憑證真偽與欄位語意需由 Codex CLI/上游認證機制處理,action 不應猜測或拒絕未來相容欄位。"
},
{
"location": "app/main.js:20",
"role": "Leo",
"original_finding": "建議至少加上 `console.error` 或在開發/除錯模式下將錯誤拋出,以便在清除失敗時能收到警示。",
"reason": "AI 對話收斂判定為誤報(問題在最新程式碼中不成立或不適用)"
},
{
"location": "app/main.js:125",
"role": "Mage",
"original_finding": "這裡直接使用 `spawn` 執行 `codex` 命令,且參數 `prompt` 是直接從 `process.env.PROMPT` 讀取並傳入的。如果 CI 環境的 `PROMPT` 被惡意竄改,雖使用陣列傳遞參數避免了 shell injection,但 `codex exec` 的邏輯若沒有妥善限制(例如限制可執行指令類型),可能導致攻擊者在 CI Runner 環境執行任意指令。",
"reason": "此 action 的目的就是讓呼叫 workflow 以 `PROMPT` 指定 Codex 任務並在隔離 CI 容器內非互動執行;prompt 語意必須由 workflow 與 secret 的信任邊界控管。程式已用 `spawn` 參數陣列避免 shell injection,不適合在 action 內以白名單改寫或限制使用者 prompt。"
},
{
"location": "app/main.js:134",
"role": "Maya",
"original_finding": "對於 codex 執行失敗的各種細節(權限不足、找不到 binary 等)都統一處理為 status: 1,測試未驗證具體錯誤來源。",
"reason": "此 GitHub Action 對外輸出以 `status=completed|failed` 與 `output` 訊息表達成功或失敗;process exit code 只需反映 Codex 子程序結果或通用啟動失敗。細分 ENOENT、EACCES 等 Action exit code 會改變既有介面且對 workflow 判斷價值有限,本次已用簡潔 output 訊息與測試覆蓋具體錯誤來源。"
}
]