本卡屬 FR-114(母卡 CM-2019),補完 CM-2053(5A-2,SUMMARY #17)只能在全量 build 產物上驗的兩點。唯讀驗證卡:只在 188 產物的副本上做,不部署、不動容器、不改原產物。可與打包修正卡並行。
CM-2053 把驗簽零件編進主程式,擋「換掉驗簽零件,整套防竄改就失效」。三個驗收點中①已由 build 證據成立(產物內無 cryptography 的 .py、manifest core 層列有 _rust.so 與 _cffi_backend.so)。剩兩點:②產物根目錄有原樣附帶的 typing_extensions.py、six.py(grpcio、python-dateutil 的相依被遞迴收進來,manifest 歸 thirdparty、開機不核對),它們同時也編進了主程式。要確認開機時真正執行的是編進去的那份,不是根目錄那支沒驗過的 .py——不能看 __file__,Nuitka 會把編入模組的 __file__ 設成「假如檔案存在的路徑」,看不出來。③在副本上換掉驗簽零件,開機要被完整性檢查擋下(修之前是放行)。
188 /opt/guidant-ai-be/.build/dist/guidant-ai-1.20.0 run5 產物(BE 99b0721c3,manifest 已簽)
⚠️ 產物權限是 700/600(另一張卡在修),複製副本時照原 owner 跑即可
產物根目錄:typing_extensions.py、six.py(原樣);guidant-ai(主程式);cryptography/hazmat/bindings/_rust.so;_cffi_backend*.so
scripts/build/build_release.sh:382-446 相依遞迴收集(為什麼會附帶 typing_extensions/six)
cp -a 產物到 188 暫存目錄(例 /tmp/cm2053-verify/),所有動作只在副本上。開機需要的 env(DB 等):照 smoke 的方式指一顆新建的臨時庫(做法同 CM-2110 甲案:init.sh+migrate.sh),用完 DROP;或確認開機完整性閘門在連 DB 之前就判定,若是則不必連 DB——先讀 jedi_integrity/app/startup_gate.py 確認閘門順序再決定。strace -f -e trace=openat,open,stat -o /tmp/cm2053-verify/trace.txt ./guidant-ai(或 smoke 的啟動命令),讓它跑到完整性閘門結束(成功起服務或被擋都可),然後 grep trace:有沒有打開根目錄的 typing_extensions.py、six.py,或任何 thirdparty 層的 .py;若有,記下是在閘門之前還是之後(對照 stderr 的 [INTEGRITY] 行時間點)。188 若沒有 strace 就回寫,不要自己裝套件。cryptography/hazmat/bindings/_rust.so 附加 1 byte 後啟動 → 預期被完整性檢查擋下(stderr 有 FATAL/起 lockdown 殼)。還原後對 _cffi_backend*.so 做一次同樣測試。每次都從乾淨副本重來。一句話:③ 成立;② 對 six/typing_extensions 成立,但實測時發現旁邊有一個更大的洞——根目錄的 google_auth_httplib2.py 和整批 thirdparty 的 .py/.pyc 是開機時從磁碟讀的、沒被驗過,改了會照跑。