FlawOpen

flawopen.com/Teardowns/cve-2026-105752-vllm-harmony-cache-salt-omission

● CVE-2026-105752 · CVSS 3.1 · 低
セキュリティ研究 · FlawOpen

CVE-2026-105752:vLLMのcache_salt欠落

vLLM ResponsesのGPT-OSSツール継続処理ではcache_saltが欠落し、saltなしのプレフィックスキャッシュ領域が使われる可能性がありました。vLLM 0.30.0以降へ更新し、すべての継続処理でテナントごとのsaltを維持してください。[1], [5]

💡 わかりやすい解説 (ELI5)

顧客ごとの書類が専用色札付きのロッカーに保管されていると想像してください。最初のリクエストには正しい札が付きますが、ツールが次の段階へ書類を戻すとき札が抜けます。共有棚はキャッシュヒットで推測したページ群の有無を示すことがありますが、ページそのものは渡しません。[1]

主要な概念と専門用語

Prefix caching
同じプレフィックスのモデルkey/valueブロックを再利用する仕組み。[6]
cache_salt
異なるsaltのキャッシュを分離するため、最初のブロックのハッシュに混ぜる値。[6]
Harmony continuation
Harmony応答後の次のモデル入力。ツール呼び出し後も含む。[1]
Membership oracle
推測したプレフィックスの有無を示し、内容は明かさないシグナル。[1]
CWE-524
機微情報を含むキャッシュの使用。アドバイザリの主な分類。[1]

フレームワーク対応

  • このガイドで説明する弱点の CWE 参照: CWE-524

根本原因の分析 (Root Cause)

vLLMアドバイザリはPOST /v1/responsesのGPT-OSS Harmony経路を説明しています。最初の入力はrequest.cache_saltをtokens_inputへ渡しますが、組み込みまたはMCPツール呼び出し後の継続処理はsaltなしのtokens_input(token_ids)を使いました。helperはsaltが渡されたときだけ保存します。自動プレフィックスキャッシュを使う共有環境では、継続処理がsaltなしの領域を使います。影響範囲は0.30.0未満とされ、0.25.1で確認されていますが、それ以前の下限は未確定です。結果はcached_tokens_per_turnによるキャッシュ所属のシグナルで、任意のプロンプト本文の直接開示ではありません。CWE-200も影響分類に挙げられていますが、ここではCWE-524のみを主な弱点とします。[1], [3], [4]

ステップ・バイ・ステップの攻撃フロー

ステップ 1

共有サービスが前提条件を満たす

影響バージョン、GPT-OSS Harmony Responses、プレフィックスキャッシュ、ツールが必要です。被害側はcache_saltを設定し継続処理に到達します。[1]

ステップ 2

最初のエンジン入力にsaltが付く

最初のtokens_input呼び出しはrequest.cache_saltを含み、プレフィックスを呼び出し元のsalt付き領域に置きます。[1]

ステップ 3

ツール継続処理でsaltが失われる

ツール結果後、継続処理は元のsaltなしでtokens_input(token_ids)を呼び、共有のsaltなし領域に入る可能性があります。[1]

ステップ 4

キャッシュ数が所属を示す可能性がある

別テナントがそのプレフィックスを再構成できればcached_tokens_per_turnで存在を推測できますが、任意のプロンプト本文は取得できません。[1]

ステップ 5

rendererが各ターンでsaltを維持する

マージ済みrenderer再構成はHarmony描画中にcache_saltを保持し、各エンジン入力へ渡します。0.30.0以降へ更新してください。[1], [3], [7]

ソースコード比較:脆弱 vs 堅牢化

vLLMアドバイザリはPOST /v1/responsesのGPT-OSS Harmony経路を説明しています。最初の入力はrequest.cache_saltをtokens_inputへ渡しますが、組み込みまたはMCPツール呼び出し後の継続処理はsaltなしのtokens_input(token_ids)を使いました。helperはsaltが渡されたときだけ保存します。自動プレフィックスキャッシュを使う共有環境では、継続処理がsaltなしの領域を使います。影響範囲は0.30.0未満とされ、0.25.1で確認されていますが、それ以前の下限は未確定です。結果はcached_tokens_per_turnによるキャッシュ所属のシグナルで、任意のプロンプト本文の直接開示ではありません。CWE-200も影響分類に挙げられていますが、ここではCWE-524のみを主な弱点とします。 Upstream excerpts, not a literal line-by-line diff.[1], [3], [4], [7]

ソース抜粋: vLLM Responses Harmony renderer(異なるリビジョンの抜粋)

脆弱な実装
# 初回リクエスト経路では salt を使っていたが、ツール実行後の継続経路では使っていなかった。
engine_input = tokens_input(token_ids, cache_salt=request.cache_salt)

# ツールの結果を受け取った後、継続処理は次のように入力を再構築していた:
engine_input = tokens_input(token_ids)
堅牢化されたセキュアパッチ
# Harmony のレンダリングコンテキストでリクエストの salt を保持する。
cache_salt = cast(str | None, engine_input.get("cache_salt"))
engine_input = self.online_renderer.render_responses_harmony_messages(
    context.messages,
    cache_salt=cache_salt,
    tok_params=tok_params,
)

# レンダラーはエンジン入力を作成するたびに salt を渡す。
engine_input = tokens_input(prompt["prompt_token_ids"], cache_salt=cache_salt)

エンジニアリング&システム堅牢化チェックリスト

参考資料