跳到主要內容
回到證據牆

PyJWT / CVE-2022-29217

HMAC 金鑰黑名單漏掉的公鑰格式

歷史漏洞識別命中(歷史測試)PyPI

HMAC 演算法只擋部分公鑰字串,ssh-ed25519 等 OpenSSH 公鑰可被當成 HMAC 密鑰,攻擊者可用公開的公鑰簽出被接受的 token。

證據鏈

依來源逐段核對。缺少的材料會明示,不以公告或修補連結代替產品測試。

  1. 產品觀測

    以發布封存檔做 L0 掃描(不給提示),輸出符合掃描前登錄的位置與 CWE;這是已知漏洞的識別,不代表原創發現或利用成功。

    封存版本掃描結果
  2. 人工/上游歸屬

    公告寫明由 Aapo Oksman(Nixu)揭露;修補歸屬見 PyJWT 公告。Vettalon 只做已知漏洞的識別測試。

    上游公告
  3. 修補對照

    同一組參數也掃了上游修補版,記錄修補後的程式碼是否仍被標記。這是掃描對照,不是利用或差分測試。

    修補版掃描對照
  4. 未驗證範圍

    模型可能在訓練時看過這份公告或修補,所以命中不能證明它是從程式碼推理出來的。候選與 needs_human 都不是自動確認,這次也沒有跑 PoC 或任何利用。單次執行,模型輸出有隨機性。五筆案例是挑過的已知漏洞,不能拿來推估召回率或誤報率。其他輸出只公開數量,沒有審閱。原始 report.json 與 trace 不公開,只列 SHA-256。表格的執行狀態照錄產品回報;incomplete 代表有單元延後、截斷、失敗或沒能交叉核對,原因列在旁邊,但每一臂的目標檔都有送審。修補版「未被標記」只表示對應範圍沒有符合 CWE 清單、且沒被駁回的輸出,同一臂的其他輸出沒有審閱,不能當成修補版沒有其他問題。2.4.0 封存檔內以公告編號命名的回歸測試 tests/test_advisory.py 在掃描前移除;2.3.0 沒有這個檔案。

    閱讀限制

這筆證據支持什麼

2.3.0 封存檔掃描在 jwt/algorithms.py:193(HMACAlgorithm.prepare_key)提出 CWE-327 候選,grok 判 plausible,最後是 needs_human,符合預先登錄的標準。修補版 2.4.0 同參數掃描,對應範圍沒有符合 CWE 清單的輸出。

測試方法

從官方套件庫下載脆弱版與修補版的發布封存檔,核對 SHA-256 後掃描整個樹,沒有 git 歷史。兩版用同一組參數:deep profile、claude 找洞、grok 與 agy(GPT-OSS)跨家族覆核、最多 8 個審查單元、每個候選覆核 1 次、PoC 關閉。模型輸入不含 CVE 編號、公告文字或修補 diff,兩版都先移除 changelog。比對標準(檔案、行號範圍、CWE 清單)在 2026-10-20 12:51 UTC 公開提交,第一次掃描在 29 秒後開始。登錄檔內的 registeredAt 寫 12:55,是提交前手填的估計,與實際不符;以提交時間為準,檔案沒有再改,所以雜湊不變。

模式
release-archive
判定
needs_human
位置
jwt/algorithms.py:193
下載公開紀錄(JSON)

公開識別證據摘要

HMAC 金鑰黑名單漏掉 OpenSSH 的 EC/EdDSA 公鑰,可造成 HS256 演算法混淆。

grok:plausible。覆核沒有駁倒候選,結論停在 needs_human,不算確認。

找洞模型
claude-opus-5-5 (Anthropic)
覆核模型與判定
grok-4.7 (xAI): plausible
工具版本
vettalon 0.3.0 (built from source on 2026-10-20)
模型版本
Finder claude-opus-5-5 (claude CLI 2.1.300); verifiers grok-4.7 (grok CLI 1.0.62) and gpt-oss-120b-medium (agy 1.4.3)
當時範圍
Whole release archive, no git history; up to 8 audit units; changelog files removed from both arms; L0 (no CWE, location or advisory hint)

重跑識別步驟

先安裝 Vettalon CLI,並在 config.toml 設定自己的模型與憑證。以下下載官方發布封存檔、核對 SHA-256 後掃描整個樹;預先登錄檔列出排除的檔案。模型與規則版本可能不同,結果不保證相同。deep 模式會把原始碼送到你設定的模型。這是識別測試,不執行上游專案,也不驗證利用。

curl -sSfLo release-archive https://files.pythonhosted.org/packages/1d/8e/01bdcfdbb352daaba8ea406d9df149c5bba7dbf70f908d4fa4c269fe6a08/PyJWT-2.3.0.tar.gz
shasum -a 256 release-archive   # expect b888b4d56f06f6dcd777210c334e69c737be74755d3e5e9ee3fe67dc18a0ee41
mkdir release-tree && bsdtar -xf release-archive --strip-components 1 -C release-tree
# remove the files listed under "excluded" in the pre-registration, then:
vettalon scan ./release-tree --profile deep --config ./config.toml --finders claude --verifiers grok,agy --max-modules 8 --refuter-runs 1 --no-prior --time-budget 2400 --report ./result.json

預先登錄的封存版本掃描

兩個臂都掃官方發布的封存檔(非 git 歷史),參數相同,模型輸入不含 CVE 編號、公告文字或修補 diff。命中與否依掃描前公開登錄的檔案、行號範圍與 CWE 判定;其他輸出只列數量,未審閱。修補版「未被標記」只代表對應範圍沒有符合標準的輸出。模型可能在訓練時看過這份公告,候選也不等於自動確認。

掃描臂版本判定模型呼叫執行狀態目標檔送審
脆弱版2.3.0命中10incomplete (injection_uncrosschecked)是
修補版2.4.0未被標記10incomplete (injection_uncrosschecked)是
下載本案掃描摘要(JSON)
摘要附件 SHA-256cf7636c10081000a50f1f26a7d76c5b29d369e8289f8c8f675ac31f709bc1f08

比對標準在第一次掃描前公開登錄: 預先登錄檔(JSON)

預先登錄檔 SHA-2566c7ef71cffa3729de787444c67823b01afcda71d61b42f2a005fda892a07db91

限制與前提

模型可能在訓練時看過這份公告或修補,所以命中不能證明它是從程式碼推理出來的。候選與 needs_human 都不是自動確認,這次也沒有跑 PoC 或任何利用。單次執行,模型輸出有隨機性。五筆案例是挑過的已知漏洞,不能拿來推估召回率或誤報率。其他輸出只公開數量,沒有審閱。原始 report.json 與 trace 不公開,只列 SHA-256。表格的執行狀態照錄產品回報;incomplete 代表有單元延後、截斷、失敗或沒能交叉核對,原因列在旁邊,但每一臂的目標檔都有送審。修補版「未被標記」只表示對應範圍沒有符合 CWE 清單、且沒被駁回的輸出,同一臂的其他輸出沒有審閱,不能當成修補版沒有其他問題。2.4.0 封存檔內以公告編號命名的回歸測試 tests/test_advisory.py 在掃描前移除;2.3.0 沒有這個檔案。

來源與歸屬

公告寫明由 Aapo Oksman(Nixu)揭露;修補歸屬見 PyJWT 公告。Vettalon 只做已知漏洞的識別測試。

原始識別報告 SHA-256

雜湊供持有原報告者比對;下載內容為人工整理紀錄,不包含原始掃描報告。

81fb9120cbb14c416b5ec50f84185a4bae09ff7478d72b51cb2e769ac34baf94