cJSON 十年岌岌可危:獨立研究揭露 33 個尚未修補的安全漏洞
oss-security 郵件論壇(Openwall)· 2026-07-31
開源 C 語言 JSON 函式庫 cJSON 近日被資安研究者 Joshua Rogers 揭露存在 33 個安全性缺陷,涵蓋 use-after-free、堆疊耗盡、整數溢位與資料競態等多種類型。這些問題透過 oss-security 郵件論壇於 2026-07-31 公開討論,但截至目前官方尚未釋出任何修補版本。cJSON 廣泛被 vendored 進 ESP-IDF 等嵌入式韌體與大量開源專案原始碼中,影響面遠超一般套件掃描能覆蓋的範圍。
漏洞機制
研究者表示,這批漏洞是「混合 AI 輔助、人工模糊測試(fuzzing)與程式碼審查」所得,每一項都附有可用 cc -fsanitize=address,undefined 編譯重現的 PoC。多數問題集中在記憶體生命週期管理錯誤:use-after-free 與別名(aliasing)假設失效是最常見的根因,例如 overwrite_item()、cJSONUtils_ApplyPatches()、merge_patch()、cJSON_ReplaceItemViaPointer() 在刪除節點時,並未考慮呼叫者傳入的是被其他結構借用(reference)或彼此重疊的指標。
另一大類問題出在遞迴與複雜度控制缺失。cJSON_ReplaceItemInArray()、cJSON_Duplicate_rec() 對帶有循環參照的輸入沒有深度限制,可能導致堆疊耗盡;cJSON_Compare() 更因演算法本身具有 2^depth 的指數時間複雜度,可被惡意建構的巢狀 JSON 觸發阻斷服務(DoS)。此外 cJSON_DetachItemViaPointer()、apply_patch() 對 parent->child 或 valuestring 缺乏 NULL 檢查,可直接造成 NULL pointer dereference。
剩下的問題多涉及 JSON Pointer(RFC 6901)解碼、merge patch 與數值精度處理:decode_pointer_inplace()、decode_array_index_from_pointer() 存在逸出序列的差一錯誤與整數環繞(wraparound)風險;generate_merge_patch()、detach_path() 因大小寫敏感旗標未被正確遵守,導致比較結果與實際資料不一致,形成資料遺失或結構破壞;而 print_number()、parse_number() 則以 epsilon 比較和缺乏範圍檢查的方式,悄悄將超出範圍的浮點數轉為 infinity 或造成靜默捨入。
- use-after-free 群集:
overwrite_item、cJSONUtils_ApplyPatches、merge_patch、cJSON_ReplaceItemViaPointer - 堆疊耗盡:
cJSON_ReplaceItemInArray、cJSON_Duplicate_rec - 指數級 DoS:
cJSON_Compare(2^depth 時間複雜度) - NULL pointer dereference:
cJSON_DetachItemViaPointer、apply_patch - JSON Pointer 解碼錯誤:
decode_pointer_inplace、decode_array_index_from_pointer、get_item_from_pointer - 數值處理錯誤:
print_number、parse_number、parse_hex4 - 未定義行為與資料競態:
cJSON_SetValuestring、cJSON_CreateNumber、cJSON_Version(靜態緩衝區與全域錯誤狀態)
受影響版本
根據研究者驗證,這 33 個問題「存在於截至 v1.7.19(含)為止的每一個版本,且全部都仍存在於目前的程式碼中」。由於 cJSON 專案近四年開發活動停滯,已知有多個修補程式碼躺在 GitHub issue 中未被合併,目前沒有任何已知的官方修復版本可供升級。
由於 cJSON 是被大量嵌入式系統(如樂鑫 ESP-IDF)與其他開源專案直接以原始碼 vendored 引入,而非透過套件管理器安裝,受影響範圍難以單純靠掃描套件版本號估算,下游維護者需要自行盤點原始碼樹是否內嵌了 cJSON.c/cJSON_Utils.c。
修補與緩解
oss-security 討論串中,發行版維護者針對是否仍有平台實際使用該函式庫展開討論,但尚未出現官方 patch release。下游若無法等待上游合併修補,可行的緩解方式包括:在呼叫端自行加上遞迴深度限制——例如在呼叫 cJSON_Duplicate 或刪除操作前限制輸入 JSON 的巢狀深度;避免對不受信任輸入呼叫 cJSON_Compare;以及在 merge patch 流程中避免依賴使用者提供、未經驗證的路徑字串。
其中一種典型的漏洞模式是刪除前未檢查 NULL:
/* DetachItemViaPointer 相關路徑 */
parent->child->prev = item->prev;
/* parent->child 可能為 NULL,呼叫前未經檢查 */sigstore-go 簽章驗證漏檢時間窗,自管長效金鑰恐被過期簽章矇混
GitHub Advisory Database · 2026-07-31
Sigstore 官方 Go 函式庫 sigstore-go 被發現在驗證簽章時,並未檢查簽章時間戳記是否落在簽章金鑰的有效期間內。此問題編號 CVE-2026-54787,對應 GitHub Security Advisory GHSA-wqqc-jjcq-vfxm,已於 2026-07-31 由 GitHub Advisory Database 完成 review 並公開。受影響情境限定於使用者自行管理、未搭配 Fulcio 憑證的長效金鑰(self-managed long-lived keys without certificates),嚴重性為 CVSS 3.1 低風險。
漏洞機制
Sigstore 一般透過 Fulcio 簽發的短效憑證搭配 Rekor 透明度日誌(transparency log)記錄簽章當下的時間戳記,驗證端再確認該時間點落在憑證有效期間內,藉此排除過期金鑰仍可用於簽章的風險。但對於不使用憑證、由使用者自行管理的長效金鑰,sigstore-go 改以 ExpiringKey 型別來表達金鑰的有效期間語意,讓呼叫端得以宣告一把金鑰何時失效。
問題在於,雖然 API 合約透過 ExpiringKey 明確要求遵守金鑰的有效期間,實際驗證邏輯卻從未真的比對 bundle 簽章時間與金鑰有效期間視窗。這代表只要攻擊者持有一把已標示逾期的金鑰材料,仍可用該金鑰產生簽章並通過 sigstore-go 驗證,即使簽章時間點落在金鑰授權使用的時間範圍之外。
此弱點對應CWE-324(使用已過期金鑰),CVSS 向量為 AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N,代表雖可遠端觸發,但攻擊複雜度高、需要低權限,且僅影響完整性、不影響機密性與可用性。
受影響版本
- 受影響:
github.com/sigstore/sigstore-go <= 1.2.0(使用 ExpiringKey 驗證流程的所有版本) - 已修補:
sigstore-go 1.2.1
由於此問題只影響使用者自行提供、未搭配 Fulcio 憑證的長效金鑰驗證路徑,採用預設 keyless 簽章(短效憑證+Rekor)流程的使用者不受影響,僅自建 PKI 或長效簽章金鑰的整合方需要留意。
修補與緩解
修補已合入 commit 4594ab4(對應 PR #642),並隨 1.2.1 版釋出。升級至 sigstore-go 1.2.1 或更新版本是官方建議的修復方式,升級後驗證器會確實比對簽章時間與金鑰有效期間視窗,拒絕落在視窗外的簽章。
對於仍在使用舊版、短期無法升級的整合方,建議暫時避免在驗證流程中信任自管長效金鑰簽出的簽章,改以搭配憑證的 keyless 簽章流程作為過渡緩解措施,直到升級完成為止。
wasmtime 修補跨引擎型別混淆漏洞,多 Engine 混用恐致越界寫入
RustSec Advisory Database · 2026-07-31
WebAssembly 執行環境 wasmtime 修補了一個可能導致型別混淆(type confusion)的安全問題——當程式同時建立多個 Engine,並讓來自不同 Engine 的物件混用於同一 Store 時,內部以「每個引擎各自唯一」的原始索引做查找,可能回傳錯誤結果。此問題編號 RUSTSEC-2026-0222,對應上游 GHSA-hgjw-h833-99q9,於 2026-07-31 公開,嚴重性為 CVSS 3.8 低風險,未分配 CVE 編號。
漏洞機制
在 wasmtime 架構中,Engine 保存編譯期產生的型別註冊表(type registry),Store 則是執行期物件(instance、function 等)的容器,理論上一個 Store 只應存放來自同一 Engine 的物件。問題在於部分 API 並未驗證傳入物件所屬的 Engine 是否與 Store 所屬 Engine 一致,包括 Instance::new、InstancePre::instantiate、Store::debug_register_module、Tag::new 等函式。
由於型別索引是「每個引擎各自唯一」的原始數值,一旦物件跨越 Engine 邊界被使用,這些索引在另一個 Engine 的型別註冊表中可能剛好對應到完全不同的型別定義,導致查找回傳格式相符但語意錯誤的資料,形成型別混淆。
最嚴重的後果出現在 trampoline 機制上——host 為某個函式簽章(signature)編譯出的 trampoline,若被誤用在簽章不同的 Wasm 函式上,可能導致 host 端在寫回傳值時越界寫入(out-of-bounds write)超出堆疊配置範圍。官方也強調,此漏洞需要 embedder 程式碼主動建立多個 Engine 並混用物件,單純執行 guest 端 WebAssembly 模組並不能觸發。
受影響版本
- 受影響:
<= 24.0.11 - 受影響:
25.0.0 - 36.0.12 - 受影響:
37.0.0 - 46.0.1 - 受影響:
47.0.0 - 47.0.2
對應修補版本分別為 24.0.12、36.0.13、46.0.2、47.0.3,涵蓋 wasmtime 24.x 到最新 47.x 的多條維護分支,顯示此問題橫跨多個發行系列存在已久。所有目前仍在維護的分支都各自收到對應修補版本,並非只修最新版。
修補與緩解
官方修補在受影響的 API 呼叫路徑中加入 Engine 一致性檢查,確保傳入 Store 的物件確實來自同一個 Engine,避免使用「跨引擎不具意義」的原始型別索引做查找。將 wasmtime 升級至對應分支的修補版本是官方建議的唯一修復方式。
若暫時無法升級,可行的緩解方式是避免在單一行程中建立多個 Engine 並跨 Engine 混用物件,例如不要把某個 Engine 建立的 Instance 或 Tag 傳入另一個 Engine 對應的 Store 中使用,即可規避此問題觸發的前提條件。
原始來源:RustSec Advisory RUSTSEC-2026-0222、GitHub Security Advisory GHSA-hgjw-h833-99q9