0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LiteLLMのCVE-2026-35029に備える:版数とマスターキーを点検するスクリプト

0
Posted at
title: "LiteLLMのCVE-2026-35029に備える:版数とマスターキーを点検するスクリプト"
tags:
  - LiteLLM
  - AI
  - Python
  - セキュリティ
  - LLM
private: false

---

TL;DR

  • LiteLLM Proxyの/config/updateに認可の不備があり、読み取り専用アカウントから管理者の乗っ取りまで到達できた(CVE-2026-35029、修正版1.83.0、CVSS v4.0で8.7)(※1)。
  • 本稿は手順中心の実践編である。自分の環境のLiteLLMが修正版かどうか、マスターキーが既定値のままでないかを点検する小さなスクリプトを作る。
  • スクリプトの動作は、版数とサンプルのYAMLで確認した(Python 3.13、2026-11-04)。脆弱な環境での攻撃の再現は行っていない。
  • 背景と攻撃の流れは、同日のZenn記事に書いた。本稿はTips寄りで、重複を避けている。

1. 先に確認すること:3つの質問

次の3つに答えられなければ、まず確認してほしい。

  1. 運用中のLiteLLMのバージョンは1.83.0以上か。(GHSAは1.82.6までを影響範囲として列挙している(※1))
  2. マスターキーは設定されていて、sk-1234のような例示値ではないか。(Zenityによれば、認証はマスターキーが設定されている場合にだけ強制され、観測された攻撃は既定のキーや未設定の環境を狙っていた(※2))
  3. 管理画面と/config/update、/get_imageが、インターネットから到達できる状態になっていないか。

1と2は、スクリプトで確認できる。3は、ネットワーク側の確認が必要である。

2. 点検スクリプト

インストール済みのLiteLLMの版数を読み、修正版(1.83.0)と比べる。インストールされていない環境(別サーバーの設定を点検する場合など)では、版数を引数で渡せる。設定ファイルを渡すと、master_keyの値も見る。

# ll_check.py(Python 3.13、標準ライブラリのみ)
import re, sys, os
from importlib import metadata

FIXED = (1, 83, 0)
WEAK_KEYS = {"sk-1234", "sk-12345", "changeme", "password", ""}

def parse(v):
    return tuple(int(x) for x in re.findall(r"\d+", v)[:3])

def check_version(v):
    return "OK" if parse(v) >= FIXED else "VULNERABLE"

def check_config(text):
    findings = []
    m = re.search(r"master_key\s*:\s*['\"]?([^'\"\n#]*)", text)
    if not m:
        findings.append("master_key の記載なし(環境変数 LITELLM_MASTER_KEY で設定している場合は別途確認)")
    else:
        val = m.group(1).strip()
        if val.startswith("os.environ/"):
            findings.append(f"master_key は環境変数参照: {val}")
        elif val in WEAK_KEYS:
            findings.append(f"弱い/既定のmaster_key: '{val}' → 直ちに変更")
    return findings

if __name__ == "__main__":
    try:
        ver = metadata.version("litellm")
    except metadata.PackageNotFoundError:
        ver = sys.argv[1] if len(sys.argv) > 1 else None
    if ver:
        print(f"litellm {ver}: {check_version(ver)} (修正版は 1.83.0 以降)")
    else:
        print("litellm 未インストール。バージョンを引数で渡してください")
    if len(sys.argv) > 2:
        for f in check_config(open(sys.argv[2], encoding='utf-8').read()):
            print("-", f)

使い方は次のとおり。

# インストール済みの環境で
python3 ll_check.py

# 版数を手で渡し、設定ファイルも点検する
python3 ll_check.py 1.80.0 config.yaml

3. 動作確認の結果

版数の判定は、境界の前後で確かめた(2026-11-04、筆者環境)。

$ for v in 1.74.0 1.82.6 1.83.0 1.95.1; do python3 ll_check.py $v; done
litellm 1.74.0: VULNERABLE (修正版は 1.83.0 以降)
litellm 1.82.6: VULNERABLE (修正版は 1.83.0 以降)
litellm 1.83.0: OK (修正版は 1.83.0 以降)
litellm 1.95.1: OK (修正版は 1.83.0 以降)

設定ファイルの点検は、次の2つで確かめた。

$ cat c1.yaml
general_settings:
  master_key: sk-1234
$ python3 ll_check.py 1.80.0 c1.yaml
litellm 1.80.0: VULNERABLE (修正版は 1.83.0 以降)
- 弱い/既定のmaster_key: 'sk-1234' → 直ちに変更

$ python3 ll_check.py 1.90.0 c2.yaml     # master_key: os.environ/LITELLM_MASTER_KEY
litellm 1.90.0: OK (修正版は 1.83.0 以降)
- master_key は環境変数参照: os.environ/LITELLM_MASTER_KEY

環境変数を参照している場合は、参照先の値までは見ていない。環境変数の中身がsk-1234でないかは、別途確認が必要である。

4. 点検後の対処

4.1 版数がVULNERABLEだったとき

  1. 1.83.0以降へ更新する。GHSAによれば、設定レベルの回避策はなく、更新が唯一の根本対策である(※1)。
  2. 更新前に、脆弱な版を公開していた期間を確認する。
  3. その期間にインターネットから到達できた場合は、侵害を疑い、次の4.3に進む。

4.2 マスターキーが既定値だったとき

例示値のままでは、攻撃者がそのキーで管理APIを呼べる。次の手順で変更する。

  1. 十分に長いランダムな値を生成する。
  2. 環境変数(または秘密管理サービス)から読ませる。設定ファイルに平文で書かない。
  3. 変更後、古いキーでの接続が拒否されることを確認する。
python3 -c "import secrets; print('sk-' + secrets.token_urlsafe(32))"

上のコマンドは、Pythonの標準ライブラリで、推測されにくい値を生成する例である。

4.3 侵害が疑われるとき

Zenityの記述では、攻撃の連鎖でデータベースの接続文字列、プロバイダーのAPIキー、Langfuseのキーなどが読み取れる(※2)。次の順で進める。

順序 対処 補足
1 外部公開を止める 管理画面と/config/update、/get_imageを遮断
2 ログを確認する /config/updateの呼び出し、UI_LOGO_PATHの変更、不審なパススルーエンドポイント
3 秘密情報をローテーションする DB接続、各プロバイダーのAPIキー、Langfuseのキー、マスターキー
4 プロバイダー側の利用量を見る 急な増加は、鍵の不正利用の兆候
5 管理者アカウントを確認する UI_USERNAMEとUI_PASSWORDが書き換えられていないか

5. ハマりやすい点

  • 版数が取れない。 pip showで見つからない環境(コンテナの外で動かしている場合など)では、引数で版数を渡す。コンテナのイメージのタグも確認する。
  • latestタグの落とし穴。 イメージのタグが固定されていないと、再起動のたびに版数が変わりうる。点検時の版数を記録しておく。
  • 環境変数の参照。 os.environ/…の形式は、スクリプトでは中身を見ていない。実際の値を別途確認する。
  • 版数の情報源が混ざる。 第三者のサイトには、別の版数(1.95.0)やCVSS(8.1)で書かれた勧告も載っていた(※3)。筆者は一次情報で確認できなかったため、本稿ではCVE-2026-35029の1.83.0を基準にした。より安全側の版数に更新して損はない。

6. 筆者の評価

点検スクリプトは、判断を単純にしてくれる。版数とキーの2点は、数秒で機械的にわかる。一方で、これだけで「安全」とは言えない。ネットワークの公開範囲や、過去の侵害の有無は、人が確かめるしかない。

そして、このスクリプトは攻撃を再現していない。判定の根拠は、GHSAに書かれた版数の範囲だけである。Zenityは1.81.0では回避が403で拒否されたとも書いており、脆弱な版の境界は資料によって揺れている。安全側に倒して、1.83.0より前はすべて対象としている。

まとめ

LiteLLMのCVE-2026-35029に備え、版数とマスターキーを点検する小さなスクリプトを作り、境界値とサンプル設定で動作を確かめた。脆弱な環境での攻撃の再現は行っていない。1.83.0以降への更新、マスターキーの見直し、管理APIの公開範囲の限定、そして侵害が疑われる場合の鍵のローテーション。この4点を、今日のうちに確認したい。

※本記事の記載内容は筆者個人の見解であり、所属する会社や組織の立場や方針とは一切関係ありません。

筆者情報

【Tomcat-zhou】|AI/AX/AIセキュリティ専門家

AI戦略洞察、AI駆動開発の方法論設計と現場で回る仕組みづくりをしています。
noteで戦略洞察 / Zenn・Qiitaで技術・方法論を書いています。
AIセキュリティ・AIコンサル・AIエージェント開発・AI活用・AI駆動開発教育、AI人材育成サービスを一体で提供。

X: @ZY20240528
LinkedIn: Tomcat-zhou
Facebook: zhou yi
note: Tomcat-zhou
Zenn: Tomcat-zhou

参考資料

  1. GHSA-53mr-6c8q-9789 / CVE-2026-35029(OSV)
  2. A Read-Only Account is All it Takes to Own a LiteLLM Server(Zenity Labs)
  3. AI Changelog Week 44(neomanex)

タグ

LiteLLM AI Python セキュリティ LLM

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?