I5 檢查結果:業務邏輯層

I5 檢查結果:業務邏輯層

檢查日期 2026-09-09|耗時 87 分鐘|對應卡片 CM-1617


§1

🔴 一句話結論

找到一個全新的問題:公司內部的套件倉庫走的是沒加密的連線,而且 26 個專案全部一樣——有心人可以在我們安裝套件時掉包,把惡意程式塞進出貨的產品裡。

另外,這一棒還回答了一個困擾很久的問題:一次檢查 40 個檔案,工具撐不撐得住?答案是撐得住。


§2

這一棒在檢查什麼

問題單的「業務邏輯層」——建單、改單、查單、標籤、成員、附件的流程安排,以及誰能做什麼的判斷。共 40 個檔案。

這是刻意的一次壓力測試:之前的經驗是「一棒不要超過 30 個檔」,這次故意放到 40,看工具撐不撐得住。


§3

找到什麼

# 嚴重度 這是什麼問題 出事會怎樣 要先有什麼才打得到 在哪裡 修正卡
1、2 🟡 中 連 GitHub 沒檢查對方身分 — — — 重複(已隨對應項修掉)
3 🟡 中
⚠️ 範圍外
舊設定檔的密碼留在版控歷史 — — — 重複;舊案殘留已清(CM-2048)
4 🟡 中 🆕 **公司內部的套件倉庫走沒加密的連線(HTTP),而且被設成「主要來源」——所有套件都從這裡下載 能在公司內網做手腳的人,可以在有人執行 poetry update 時掉包任何一個套件**。Python 安裝套件時會執行安裝腳本,等於在開發機和打包機上執行攻擊者的程式碼——而打包機產出的正是要交給客戶的安裝檔 ① 攻擊者要在公司內網、且位於開發機與套件倉庫之間
② 要有人執行 poetry update(或沒有版本鎖定檔的全新安裝)
pyproject.toml 第 77 行 ✅ 已修(版本鎖定檔入版控,連線維持 http 為決策者裁定;原卡 CM-1634 作廢)

這棒的新問題:1 個。


§4

詳細說明:內部套件倉庫走明文連線

白話:我們公司自己架了一個「套件倉庫」(叫 Nexus),所有專案要用到的套件都從那裡下載。但那個倉庫用的是沒加密的 HTTP 連線,而且被設定成「主要來源」——連公開的第三方套件也都繞道走它。

# jedi-issue/pyproject.toml 第 76-78 行
[[tool.poetry.source]]
name = "nexus"
url = "http://192.168.50.171:8082/repository/pypi-group/simple"
#      ↑ http 沒有 s,代表沒有加密
priority = "primary"
#          ↑ 主要來源,所有套件都走這條

出事會怎樣:沒加密的連線,中途可以被改。有心人在公司內網做手腳,就能在有人執行 poetry update 的時候,把某個套件換成他的版本。Python 裝套件時會執行安裝腳本,所以那等於直接在開發機或打包機上執行他的程式碼。

最麻煩的是:打包機(188 那台)產出的就是要交給客戶的安裝檔。而且被換掉的套件雜湊值會寫進版本鎖定檔,之後每次安裝都照著用——包括打包進客戶的產品裡。

首腦另外查了報告沒查的範圍:

查什麼 結果
這個專案的版本鎖定檔 93 個套件來源全部是這個 http 網址
jedi 套件庫裡有幾支這樣 25 支套件全部一樣
主專案呢 也是同一個(pyproject.toml 第 266 行)

合計 26 個專案。

為什麼是「中」不是「高」:攻擊者必須人在公司內網、而且剛好位於開發機與倉庫之間的路徑上。另外,已經有版本鎖定檔、且雜湊驗證通過的安裝不受影響——除非鎖定檔本身已經被汙染。

怎麼修:這一條不是改程式碼能解決的,要基礎設施先動:

  1. 讓 Nexus 改走 HTTPS(用公司內部的憑證也可以,前提是憑證要發到所有開發機和打包機並被信任)
  2. 然後把 26 個專案的網址從 http:// 改成 https://
  3. 過渡期的做法:把 poetry update 當成特權操作,只在可信任的網段執行

§5

🔴 這一棒最有價值的產出:40 個檔的壓力測試通過了

這比找到的問題更重要。

背景:工具的驗證機制是「三個獨立檢查員對每條發現各投一票」。範圍太大時,這些檢查員會因為額度用盡而集體掛掉——之前 FR-077 那次就是這樣,105 個檢查員全部掛掉,21 張票一張都沒投出來,整輪報告是空的。

從那之後,規矩訂成「一棒不要超過 30 個檔」。

這次故意放到 40 個檔,結果:

檔數 投票結果 當時的條件
FR-077 那次 42 ❌ 全滅(105 個檢查員全掛、21 票 0 投) 連續跑,和其他棒搶額度
這一棒 40 ✅ 15 票全投、零漏投、零中斷、一輪跑完 分開跑,獨佔額度

同樣是 40 個檔級別,一個全滅一個全過——差別不在檔數,在有沒有和別的工作搶額度。

所以規矩可以改成:「40 個檔可行,前提是一次只跑一棒。」

這一整個 arc 六棒一次都沒有撞到額度,對照 FR-079 那棒撞了兩次、跑了 14 小時、還踩到工具的併檔陷阱。這是決策者堅持「分開來跑」直接換到的結論。


§6

順帶一提:被否決的那條,證實了 I4 的結論

檢查員 3 票否決了一條「成員名單可能外洩」的候選,理由有兩個:那段程式碼沒有任何入口到得了、以及插件裝配時缺少認證設定會直接拒絕掛載。

後者正是 I4 那棒首腦自己打開檔案查到的事。工具這次獨立確認,兩邊對上了。


§7

這份結果可信到什麼程度

「這些是真的嗎」→ ✅ 可信

全部 3 票全過,15 票全數投出、零漏投、零中斷,而且檢查員沒有降低任何一條的嚴重度。第 4 條首腦自己打開檔案核對過,還多查了影響範圍(26 個專案)。

「是不是只有這些」→ ❌ 不可信

快篩模式。40 個檔裡有 18 個是幾乎空白的檔案,實際有內容的約 22 個。


§8

執行概況(技術細節)

項目 數字
檢查範圍 40 個檔案(壓力測試)
派出/回報的研究員 2 / 2
候選問題 → 去除重複 7 → 5
投票數 15(5 條 × 3 個檢查員)
沒投到票的 0
投票中斷的 0
驗證輪次 1(一輪就跑完)
耗時 87 分鐘