本卡屬 FR-195(Agent 資安修正),第 4 批 G1。首腦實質驗收 F7(CM-3830)時實測發現的副作用,從那張卡拆出來補。依賴:CM-3830 已合進工作坊 branch(
61c9118)。
F7(CM-3830)為了擋「一個特製的小壓縮包吃光記憶體」,在解壓前加了一道總量上限:解壓後的總位元組數不能超過「允許的內容大小 + 檔數上限 × 每個檔 1 KB 的餘裕」。那 1 KB 是給 tar 格式本身的開銷用的(每個檔一個標頭加補齊)。
問題是 1 KB 只夠短檔名。路徑超過約 155 個字的檔,tar 會多放兩個區塊來存長檔名,每個檔實際多佔 2 KB 以上;路徑越長越多。原始碼包裡這種深層路徑很常見(例如 node_modules 底下)。結果是:一個完全合法、內容也沒超過上限的壓縮包,只要長路徑的檔夠多、總量又貼近上限,就會被誤判成超量而拒絕。
這張卡把每個檔的餘裕調到 8 KB,涵蓋到 Linux 路徑長度上限(4,096 字)。防護不會變弱:原本要擋的攻擊是一個標頭宣告幾百 MB,8 KB 乘以檔數上限仍然遠小於那個量級。
6cf52eb 開檔核過並實測)guidant_agent/shared/archive_safety.py:214 _PER_MEMBER_OVERHEAD = 1024,上方 :213 的註解寫「tar 每個成員至多多佔 512 byte 標頭+511 byte 補齊」——這只算了一個標頭。用到它的兩處::221(壓縮檔本身大小的預檢)與 :270(_CappedReader 的上限)。max_files=2000、max_bytes=20000 → 被擋,訊息「解壓後的總大小超過允許上限」。短檔名、內容剛好等於上限的包則正常通過。vulndb_bundle.py 有自己的解壓),不受影響。guidant_agent/shared/archive_safety.py
test/test_fr177_resource_limits.py
archive_safety.py:214 把 _PER_MEMBER_OVERHEAD 從 1024 改成 8192。:213 的註解改成現況,一到兩行,講清楚為什麼是這個數字:短檔名每個成員約 1 KB(標頭+補齊),路徑超過 155 字時 tar 另放長檔名的擴充標頭與資料區塊、4,096 字的路徑約 6 KB;取 8 KB 涵蓋路徑長度上限。:221 與 :270 用的是同一個常數,不用另外改。不要改演算法(不要去解析擴充標頭、不要按實際檔名長度動態算):固定餘裕簡單、可預期,8 KB 已經夠。archive_safety.py 現在 354 行,改完行數不變。原本會被誤擋的長路徑壓縮包可以正常解壓。對惡意壓縮包的防護不變:test_tar_huge_pax_header_rejected_fast(宣告 512 MB 的擴充標頭)必須仍然被擋。