LiteLLM 1.107.0 にマルウェア(2026年10月21日):自分の環境は当たる?確かめ方と替える鍵

PR
LiteLLM 1.107.0 にマルウェア(2026年10月21日):自分の環境は当たる?確かめ方と替える鍵
この記事は約29分で読めます。

日本時間の2026年10月21日の夜、LiteLLM の 1.107.0 という版が、PyPI(Python の部品を配る公式の置き場)と Docker の登録所(Docker のイメージを配る置き場)に配られました。この版には、資格情報(パスワードや API キーのように、「その人だ」と認めてもらうためのもの)を盗む仕組みが入っていました。LiteLLM は、100 を超える AI のモデルの API を、OpenAI の形の 1 つの呼び方で呼べるようにするオープンソースのライブラリです。Python から直接使う形と、チームで 1 か所に置くサーバー(プロキシ。AI Gateway とも呼ばれます)の形があります。

LiteLLM の告知は、この版を "compiled malware"(マルウェア)と書いています。マルウェアとは、悪い働きをするように作られたプログラムのことです。ソフトの弱点(脆弱性)が見つかった件ではなく、悪い版そのものが、正規の配り場に出た件です(→「CVE の番号は付いている?」)。

先に答えを書きます。ここがいちばん大事なところです。時刻はすべて日本時間です(告知の UTC の時刻に 9 時間を足しました)。

  • まず、時間と条件に当たる操作があったかを見ます。 告知が挙げる人は、次のとおりです(すべて10月21日の日本時間)。それより前の版は安全と、告知は書いています(→「自分の環境は当たる? 告知の条件で見る」)
    • pip:20時39分〜22時23分 に、版を固定せずに(pip install litellm のように番号を書かずに)LiteLLM を入れた人
    • Docker:20時46分〜23時20分 に、イメージ(v1.107.0・latest・main-latest・main-stable)を使った(起動した)人
    • CI(自動でテストやビルドを回す仕組み):上の時間に、LiteLLM を入れた、またはそのイメージを使った実行があったか、実行の一覧の時刻で見ます
  • 確かめるときは、疑わしい環境で Python を動かしません。 pip を動かすのも Python の起動です。ファイルの上で、告知の 3 つ(litellm-1.107.0.dist-info・cook.pth・部品の置き場〔site-packages など〕のすぐ下の sitecustomize.py)を探します。Docker は、イメージを起動せずに、ダイジェスト(イメージごとの識別の文字列)を告知の値と比べます(→「どうやって確かめる? Python を動かす前にファイルを探す」)
  • 当たる操作があった、またはファイルが見つかったなら、乗っ取られたもの(盗まれた前提)として扱います。 告知の手順で、ファイルを消し、動き続けるプロセスを止め、環境を作り直し、その機械から手の届いた鍵やパスワードを全部替えます。インターネットに出られる機械なら、送り出しは成功したと考えるよう告知は書いています(→「入っていたら、何をする? 告知の手順」)
  • LiteLLM を使い続けるなら、当たっていなくても、litellm==1.106.2 のように版を決めて入れます。 流すのは、当たる操作が無かった環境か、作り直した環境です。直った新しい版は出ていません。1.107.1 という版も PyPI にありません(2026年10月23日時点)(→「当たっていなくても:版を固定する」)

初心者がまずやることは、1 つ目です。上の時間に、自分のパソコン・サーバー・CI で、LiteLLM を入れる操作や、4 つのタグのイメージを使う操作があったかを、記録の時刻で見ます。次の人は、2 つ目の、Python を動かさずに告知の 3 つを探す手順に進みます。

  • 記録が残っていなくて、分からない人
  • 自分で入れた覚えが無い人(ほかの部品の依存で入ることがあります。→「LiteLLM を自分で入れた覚えがありません。関係ありますか?」)
  • uv など、pip 以外で入れた人(告知は pip とだけ書いています。→「uv など、pip 以外で入れた人」)

書いてあることは、LiteLLM の告知・GitHub の issue・PyPI・Docker の登録所・公的機関の一覧などを、2026年10月23日の16時56分から17時7分ごろ(日本時間)に開いて確かめたものです。手元でファイルを探す手順・Docker の比べ方・文書の裏づけは、同じ日の17時45分から18時23分ごろに確かめました。悪い 1.107.0 そのものは、入れていませんし、落としてもいません。告知や公的機関の一覧は更新されることがあるので、時刻を添えました。

この記事でわかること
  • 何が配られたか(LiteLLM 1.107.0)と、当たる時間(日本時間)。ソフトの弱点ではなく、悪い版そのものが配られた件であること
  • 当たる人の条件(pip・Docker・CI)と、uv など pip 以外で入れた人の扱い
  • Python を動かさずに確かめる方法(ファイルを探す、Docker はダイジェストを比べる)
  • 入っていたときの告知の手順と、替える鍵
  • 当たっていなくてもする、版の固定(1.106.2)
  1. 10月21日に、LiteLLM に何があった?
    1. 告知が書いていること
    2. 当たる時間(日本時間)
    3. たとえ話で見ると
    4. CVE の番号は付いている?
  2. 自分の環境は当たる? 告知の条件で見る
    1. pip で入れた人
    2. CI で入れた人
    3. Docker のイメージを使った人
    4. uv など、pip 以外で入れた人
    5. 当たらないと告知が書く人
  3. どうやって確かめる? Python を動かす前にファイルを探す
    1. 先に Python を動かさない理由
    2. 探す3つのファイル
    3. Mac・Linux で探す
    4. Windows で探す
    5. Docker:イメージを起動せず、ダイジェストを告知と比べる
    6. 見つからなかったとき
  4. 入っていたら、何をする? 告知の手順
    1. 替える鍵(告知が名指しするもの)
    2. AWS で動かしていた人
  5. 当たっていなくても:版を固定する
    1. いまの版は 1.106.2(直った新しい版は出ていない)
    2. pip で版を固定する
    3. Docker はダイジェストで固定する
    4. uv で入れている人
  6. 被害と公的機関の告知は?(2026年10月23日時点)
  7. よくある質問
    1. 新しい版に上げればいいですか?
    2. ほかの記事で、Python のコマンドで版を見る方法を見ました。先にそれをしてもいいですか?
    3. LiteLLM を自分で入れた覚えがありません。関係ありますか?
    4. LiteLLM の文書にある docker.litellm.ai のイメージを使っていました。当たりますか?
    5. 1.106.2 より古い版に固定してもいいですか?
  8. まとめ
  9. 参考資料

10月21日に、LiteLLM に何があった?

告知が書いていること

LiteLLM の公式の告知は、docs.litellm.ai のブログの記事です(Contained: Oct 21, 2026 LiteLLM release v1.107.0 Compromised)。題のとおり、状態は「封じ込めた。調べている途中」("Incident contained, investigation in progress")で、最後の更新は、日本時間の10月22日 5時30分(告知では October 21, 2026 20:30 UTC)です。

告知の中心の文は、こうです。10月21日に、LiteLLM の公開の仕組み(release pipeline)が乗っ取られ、v1.107.0 が Docker の登録所と PyPI に出ました。この版には、資格情報を盗み、外からコードを動かす道具を読み込む仕組みが入っていました。それより前の版は安全で、当たった版は取り下げた、と告知は書いています。

乗っ取りの経緯は、告知の 1 文の範囲で書きます。GitHub にある正式な v1.107.0 のソースには悪いファイルは無く、当たった配布物は、攻撃者が握るリポジトリから作られた、と告知は書いています。企業向けの非公開の版(private enterprise release)を使っている人は、当たっていません。

この件の issue(GitHub の相談・報告の場)を立てたのは、LiteLLM の外の報告者です。LiteLLM の担当者が、そこに状況を書き込んできました。この種の件の全体像は、ソフトウェアのサプライチェーン攻撃とはの記事で説明しています。

当たる時間(日本時間)

告知の時刻(UTC)に 9 時間を足した、日本時間です。すべて 2026年10月21日です。

配り場名前悪い版だった時間(日本時間)
PyPIlitellm==1.107.020時39分〜22時23分(約 2 時間)
Docker Hubv1.107.0・latest・main-latest・main-stable の 4 つのタグ20時46分〜23時20分
GHCR(GitHub のイメージの置き場)の 3 つのイメージ(ghcr.io/berriai/litellm・litellm-database・litellm-non_root)同じ 4 つのタグ20時46分〜22時51分(使えなくなるまで)

ダイジェストの値はここには写しません。告知に載っています。

たとえ話で見ると

お店の棚に、いつもの商品の箱が並んでいます。ところが、ある夜、いつものメーカーの工場ではない場所で詰められた箱が、正規の配送の仕組みに乗って、棚に並んでしまいました。その箱を買って自分の部屋に置く(入れる)と、箱の中の仕掛けが、その部屋の明かりをつけるたびに動きます。箱を開けなくても、中を確かめようとして明かりをつけても、動きます。仕掛けは、家の合鍵を写して持ち出します。だから、確かめるときは明かりをつけずに、外から名前で探します。合鍵を写されたかもしれないなら、鍵を付け替えます。

例えの物と、実際の物の対応は、次のとおりです。

  • お店の棚:PyPI と Docker の登録所
  • 工場:GitHub の正式なソース。工場ではない場所:攻撃者が握るリポジトリ
  • 正規の配送の仕組み:LiteLLM の公開の仕組み(release pipeline)
  • 箱を買って自分の部屋に置く:LiteLLM を入れる・イメージを使う
  • その部屋の明かりをつけるたび:その Python を起動するたび
  • 箱の中の仕掛け:余分なファイル
  • 合鍵を写して持ち出す:資格情報を盗む

告知の言い方では、こうなります。LiteLLM の公開の仕組みが乗っ取られ、GitHub の正式なソースではなく、攻撃者が握るリポジトリで作られた配布物が、PyPI と Docker の登録所に出ました。OSV(オープンソースの脆弱性やマルウェアの記録を集めた公開のデータベース)の記録によると、1.107.0 は余分な 3 つのファイルを持ち、pip はそれを site-packages(Python の部品が入る場所)のすぐ下に入れます。そのため、litellm を import しなくても、その Python を起動するたびに動きます。告知も、当たった環境では、Python を起動するたびに cook.pth と sitecustomize.py がまた動き、pip を動かすのも含む、と書いています。

CVE の番号は付いている?

この件に CVE の番号は、2026年10月23日の17時ごろの時点で見つかりませんでした。CVE は、脆弱性に付く世界共通の管理番号です。

別の記録は付いています。GitHub Advisory Database の、マルウェアの記録(種類は "malware")GHSA-92x9-889m-jgmwに、3月の 1.82.7・1.82.8 と同じ記録に、10月22日の更新で 1.107.0 が載っています。これは LiteLLM が出した告知ではなく、GitHub のデータベースの記録です。OSV にも MAL-2026-2144 があります。

10月23日(日本時間)に NVD(アメリカの脆弱性のデータベース)に出た LiteLLM の CVE-2026-114612 は、別の件です。権限の昇格の脆弱性で、当たる範囲に 1.106.2 は入っていません。番号の読み方は、脆弱性の知らせの読み方にあります。

自分の環境は当たる? 告知の条件で見る

当たるかどうかは、告知の「Who is affected」(誰が当たるか)の文で決めます。原文の訳は、こうです。10月21日の20時39分から22時23分(日本時間。UTC の11時39分から13時23分)に、版を固定せずに pip で LiteLLM を入れた人。または、20時46分から23時20分(UTC の11時46分から14時20分)に、Docker のイメージ v1.107.0・latest・main-latest・main-stable を使った(起動した)人です。

そのうえで告知は、1.107.0 を入れた、またはその時間にイメージを使った(起動した)なら、乗っ取られたものとして扱う、と書いています。1.107.0 の入った環境で Python を起動したなら、その環境も同じ扱いです。

pip で入れた人

「版を固定せずに」とは、litellm とだけ書いて、版を決めずに入れた場合です。pip の文書は、「固定」を、== で決まった版を求めること、と説明しています。litellm>= のように下限だけを書く形は、固定ではありません。

いつ入れたかは、その日の作業の記録(デプロイや環境づくりの時刻、イメージを作った時刻など)で見ます。20時39分から22時23分の間に、版を固定せずに入れた操作があれば、当たります。

CI で入れた人

10月21日の20時39分から22時23分(日本時間)に、LiteLLM を版を固定せずに入れた実行があったかを、CI の実行の一覧の時刻で見ます。Docker のイメージを使う CI は、20時46分から23時20分です。あれば、乗っ取られたものとして扱い、その CI が持つ秘密を替えます。

実行の一覧は、GitHub なら、リポジトリの「Actions」のタブで、左の一覧からワークフローを選ぶと見られます。コマンドの gh run list --json createdAt,startedAt で出した時刻は、UTC の形でした(このブログのリポジトリで、手元で流しました)。UTC なら、pip の時間は11時39分から13時23分、Docker は11時46分から14時20分です。

GitHub が用意する実行環境(GitHub-hosted runner)は、1 CPU のものを除き、ジョブごとに GitHub の新しい仮想マシンだと、GitHub の文書は書いていますが、これは「あとに残らない」という話です。告知は、1.107.0 の入った環境で Python を起動したなら、乗っ取られたものとして扱うと書き、外のネットにつながる機械なら、送り出しは成功したと考えるよう書いています。その実行の中にあった秘密も、告知の「その機械のどのプロセスの環境変数に入っていた秘密も」に当たると読めます。自分で置く実行環境(self-hosted)には、使い捨ての保証はありません。

Docker のイメージを使った人

告知が挙げるのは、v1.107.0・latest・main-latest・main-stable の 4 つのタグを、Docker Hub は20時46分から23時20分、GHCR は20時46分から22時51分の間に、使った(起動した)人です。latest のようなタグは、指す先が付け替えられるので、手元のイメージが悪いものだったかは、ダイジェストで比べます(→「Docker:イメージを起動せず、ダイジェストを告知と比べる」)。

Docker Hub の名前は、告知に書かれていません。手元で見ると、litellm/litellm・litellm/litellm-database・litellm/litellm-non_root がありました。GHCR の名前は告知に書かれています(ghcr.io/berriai/litellm・litellm-database・litellm-non_root)。

LiteLLM の文書の Docker の始め方は、docker.litellm.ai/berriai/litellm:latest という名前を使っています。告知は、この名前を書いていません。確かめ方は、「Docker:イメージを起動せず、ダイジェストを告知と比べる」の節に書きました。

uv など、pip 以外で入れた人

告知の条件は、「pip で」とだけ書いています。uv など別の道具で入れた場合を、告知は書いていません。そのため、この記事は、uv などで入れた人が当たる・当たらないとは言いません。

確かめ方は、同じです。探すファイルの名前は同じです。dist-info の名前の形({名前}-{版}.dist-info)は、Python の部品の置き方の決まり(PyPA の仕様)で決まっていて、ふつうは site-packages に置かれます。uv の使い方は、uv の記事にあります。

uv を使うと、uv のキャッシュ(取ってきた部品の置き場)の中にも、dist-info の名前のフォルダーができました(手元で 1.106.2 を入れて見ました)。ホームから探すと、そこにも出ます。1.107.0 を uv で入れたとき、キャッシュに何が残るかは、確かめていません。

当たらないと告知が書く人

告知は、それより前の版は安全で、企業向けの非公開の版(private enterprise release)は当たっていない、と書いています。OSV の記録も、1.106.2 と 1.107.0rc1・rc2 は当たらない、と書いています。

どうやって確かめる? Python を動かす前にファイルを探す

先に Python を動かさない理由

告知は、当たった環境で Python を起動すると、どの起動でも(pip を動かすのも含めて)、cook.pth と sitecustomize.py がまた動く、と書いています。「pip での導入から始めない」とも書いています。

Python の公式の文書も、同じ向きのことを書いています。site モジュールは、起動のときに自動で読み込まれます。.pth ファイル(Python が起動のときに読むファイル)の中の、import で始まる行は実行され、その部品を使うかどうかに関わらず、Python を起動するたびに動きます。また、起動の途中で sitecustomize という名前のモジュールを読み込もうとします。

だから、疑わしい環境では、確かめるためにも Python を動かしません。ファイルの名前を、外から探します。Python の起動を一部省く方法は、告知に載っていないので、この記事では勧めません。

ここでいう環境は、LiteLLM が入っているかもしれない Python(仮想環境なら、その仮想環境)のことです。作り直すのは環境、鍵を替えるのは、その機械から手の届いたものです。

探す3つのファイル

告知が挙げる 3 つは、次のとおりです。

  • litellm-1.107.0.dist-info(1.107.0 が入ったことを記録するフォルダー)
  • cook.pth
  • sitecustomize.py(部品の置き場〔site-packages など〕のすぐ下にあるもの)

告知は、1 つ見つかれば当たったと確かめられる、見つからなくても、きれいだという証明にはならない、と書いています。

sitecustomize.py は、Python の起動のときに読み込まれる、ふつうの仕組みのファイルでもあります。見るのは、部品が入る場所(site-packages。Debian・Ubuntu の OS の Python に pip で入れた分は dist-packages)のすぐ下にある …/site-packages/sitecustomize.py です。正規の物は、場所で見分けます。Debian の Python のパッケージでは、/etc/python3.13/ や /usr/lib/python3.13/ にあります(手元の Ubuntu 24.04 では、/etc/python3.12/sitecustomize.py と、それを指す /usr/lib/python3.12/sitecustomize.py)。

Mac・Linux で探す

ファイルの名前を探すだけで、Python は動かしません。手元の Mac で、ホームから流した 1 行は、こうです。

find ~ \( -type d -name 'litellm-*.dist-info' -o -type f -name 'cook.pth' -o -type f -name 'sitecustomize.py' \) -print

~ は、自分のホームのフォルダーです。プロジェクトのフォルダーや仮想環境(プロジェクトごとに部品を分けて入れる箱)のフォルダーなど、ほかの場所を探すときは、~ をその場所に書き換えます。Linux のコンテナで機械全体を探したときは、/ から -xdev を付けて流しました(管理者の権限)。

find / -xdev \( -type d -name 'litellm-*.dist-info' -o -type f -name 'cook.pth' -o -type f -name 'sitecustomize.py' \) -print

条件を -o でつなぐときは、条件全体を \( … \) で囲んでから -print を付けます。囲まずに書くと、-print が一部にしか掛からず、見つかっても表示されないものが出ます(終了コードは 0 のままです)。手元で、正しい形と誤った形を比べて確かめました。

出てきた行の読み方は、次のとおりです。

  • litellm-1.107.0.dist-info:当たりました
  • litellm- の別の版(litellm-1.106.2.dist-info など):この件の悪い版ではありません
  • cook.pth:当たりました
  • 部品の置き場のすぐ下の sitecustomize.py:当たりました
  • それ以外の場所の sitecustomize.py(OS・Homebrew・エディターの拡張機能などが入れた物):数えません
  • uv のキャッシュの中の dist-info:「uv など、pip 以外で入れた人」の節を見てください

悪くない 1.106.2 だけが入った作業用の仮想環境で、同じ形で探すと、次の 1 行が出ました。.pth と sitecustomize.py は、ありませんでした。

<仮想環境>/lib/python3.12/site-packages/litellm-1.106.2.dist-info

手元の Mac で、ホームから探したときの結果と、その読み方です(macOS 14)。

  • 終わるまで 229 秒かかりました。長くかかることがあります
  • 画面に Operation not permitted が 171 行出ました。macOS が見せない場所(~/Library/ の下の Containers など、写真のライブラリの中)を読めなかった、という表示です。見つかった印ではありません。流したアプリに与えられた権限で、出方は変わりえます
  • find の終了コードは 1 でした。見えない場所があったためで、「見つからなかった」の意味ではありません。見えなかった場所の分は、確かめられていません
  • sitecustomize.py は 5 つ出ましたが、どれも部品の置き場のすぐ下ではありませんでした(エディターの拡張機能の Python のデバッガーの中に 3 つ、uv のキャッシュの中のよその部品の試験のファイルに 2 つ)。数えません。litellm-*.dist-info は 0 でした(この Mac のホームには LiteLLM を入れていません)
  • Homebrew の Python は、標準ライブラリの場所に、Homebrew が作った sitecustomize.py を持っています(部品の置き場の外)

Linux のコンテナで見たことです(Debian 13・Ubuntu 24.04)。

  • OS の Python に pip で入れると、dist-packages という名前のフォルダー(/usr/local/lib/python3.13/dist-packages/ など)に入ることがありました。site-packages という名前だけで探すと見落とすので、dist-info の名前で探します
  • 管理者でない利用者で find / を流すと、管理者の仮想環境(/root/…)の分は出ませんでした。管理者の権限で流すと出ました

Windows で探す

Windows では、この記事で手順を流して確かめていません。コマンドは載せません。場所だけを書きます。site-packages の場所は、Python の文書によると、<Python のフォルダー>\Lib\site-packages です。仮想環境の中にも Lib\site-packages ができます。この中で、上の 3 つの名前を探します。

Docker:イメージを起動せず、ダイジェストを告知と比べる

中を見るために、疑わしいイメージを起動しません。 手元のイメージのダイジェストを、告知の値と比べます。

ダイジェストは、イメージごとに付く識別の文字列で、元が変わらなければ同じ値になります。告知は、当たったイメージのダイジェストを載せていて、そのダイジェストのイメージを動かしたコンテナは、乗っ取られたものとして扱う、と書いています。値はこの記事に写さないので、告知を開いて比べてください。docker.litellm.ai から取った人も、同じ比べ方です。

手元にあるイメージのダイジェストは、次のどちらかで見られます。どちらも、イメージの情報を見るだけです。docker image ls --digests は、タグを付けずに、名前だけで書きます。手元で流した形は、次です(litellm/litellm は、自分が使った名前に書き換えます)。

docker image ls --digests litellm/litellm
docker image inspect --format '{{json .RepoDigests}}' litellm/litellm:v1.106.2

見るのは、docker image ls --digests の DIGEST の列か、RepoDigests の値です。手元で、悪くない litellm/litellm:v1.106.2 を取って比べたところ、docker pull の Digest: の行・DIGEST の列・RepoDigests・Docker Hub の API の値の 4 つは同じでした。docker image inspect の .Id(イメージの ID)は別の値なので、告知のダイジェストとは比べません。

動いているコンテナが、どのイメージから起動されたかは、止めずに見られます。docker ps の IMAGE の列は、起動に使った名前(タグ)を出します。タグは、あとから別のイメージに付け替えられるので、名前だけでは起動したときの中身とは限りません。次の形で、イメージの ID から引きます。

docker inspect --format '{{.Image}}' <コンテナ>
docker image inspect --format '{{json .RepoDigests}}' <出てきたイメージの ID>

この 2 つの流れも、手元で確かめました(悪くない 1.106.2 のイメージで、中の sleep だけを動かしました)。疑わしいイメージでは、この形でも起動しません。Docker の保存の形が containerd の設定の場合は、この出方を確かめていません。

告知の値と同じなら、そのイメージを動かしたコンテナは、乗っ取られたものとして扱います(→「入っていたら、何をする? 告知の手順」)。値が違っても、時間に当たる使い方があったなら、乗っ取られたものとして扱います(→「見つからなかったとき」)。

見つからなかったとき

3 つのファイルが見つからなくても、きれいだという証明にはなりません。告知がそう書いています。10月21日の20時39分から22時23分(Docker は20時46分から23時20分)に当たる操作があったなら、見つからなくても、乗っ取られたものとして扱います。

告知は、当たったかどうかの見つけ方を、もっと詳しく載せると書いていますが、2026年10月23日の時点では載っていません。載ったら、そちらを見てください。

入っていたら、何をする? 告知の手順

次の手順は、告知の "What to do if you are affected"(当たったときにすること)の内容です。LiteLLM の告知は、これを、この件を見つけるのを手伝った報告者の手順だ、と書いています。

先に、ネットの話です。告知は、外のネットにつながる機械に一度でも 1.107.0 を入れたなら、送り出し(盗んだ資格情報を外へ出すこと)は成功したと考えるよう書いています。

  1. Python を起動しません。 pip を動かすのも、Python の起動です
  2. シェル(ターミナルで打つコマンド)から、ファイルを消します。 当たった環境の部品の置き場(site-packages)のすぐ下の cook.pth・cook.py・sitecustomize.py と、__pycache__ の中の対応する cook*.pyc・sitecustomize*.pyc を消します。cook.py も消します。消すのは、見つかった悪い版の環境のものです。OS や Homebrew が入れた正規の sitecustomize.py(部品の置き場の外にあるもの)は、消しません
  3. 裏で動き続ける python のプロセスを止めます。 告知によると、このプロセスは /tmp/remote_code_loader.lock を使い続けています(ロックしています)
  4. 作り直した環境で、litellm==1.106.2 に固定して入れ直します。 イメージと仮想環境は、一から作り直すほうがよい、と告知は書いています
  5. 鍵を替えます(下の節)

替える鍵(告知が名指しするもの)

告知は、その機械から手の届いたものを全部替えるよう書き、とくに次の 4 つを挙げています。

  • インスタンスやタスクの IAM ロール(クラウドの機械に付ける権限)
  • LiteLLM のプロキシの DB に入れた、すべての提供元(AI のモデルを出している会社)の鍵と、マスターキー・仮想キー(LiteLLM の文書は、仮想キーを、利用者・チーム・プロジェクトごとに配る鍵と説明しています)
  • DATABASE_URL のパスワード
  • その機械の、どのプロセスの環境変数に入っていた秘密も

自分のパソコンで使っていた人は、上の 4 つがサーバー向けの言い方に見えるかもしれません。そのパソコンから手の届いたものを全部替えます。何が盗まれうるかは、OSV の記録の種類も見てください。OSV の記録によると、盗む対象には、次のものが挙がっています。

  • ブラウザーのパスワードと履歴
  • SSH の鍵・シェルの履歴
  • AWS/GCP/Azure の資格情報とクラウドのメタデータ
  • Kubernetes・Docker・Vault と CI の秘密
  • AI の開発の道具の設定
  • GPG と TLS の秘密鍵
  • .npmrc・.pypirc・.git-credentials
  • 環境変数

鍵を .env に置いていた人は、.env の記事の考え方が役に立ちます。AI の API キーは、本番の資格情報と同じに扱います(AI を悪用した攻撃の記事に、その考え方があります)。

AWS で動かしていた人

告知は、入れた時刻のあたりに、インスタンスのロールから GetCallerIdentity が呼ばれていないかを CloudTrail(AWS の操作の記録)で見て、そのあと、そのロールの資格情報が自分の設備の外から使われていないかを見る、と書いています。

当たっていなくても:版を固定する

いまの版は 1.106.2(直った新しい版は出ていない)

PyPI は 1.107.0 を隔離し(人が読む画面は "Quarantined")、pip が見る一覧から外しました。いま、pip が見る一覧のいちばん新しい版は 1.106.2 です。直った新しい版は、出ていません。1.107.1 という版は、PyPI にありません(2026年10月23日時点)。GitHub の Releases にも、v1.107.0 はありません。

LiteLLM は、自分たちの配り場を新しい版が出せないように閉じたまま、ふだんの版の公開も止めたままだと、10月22日に書いています。

告知が勧めるのは、次の文です。原文の訳は、「当面は(For the time being)、1.106.2 か、この告知の時点より前に出た版に、番号を決めて固定してください」です。1.106.2 は、告知と OSV の記録のどちらでも、当たらないとされています。

pip で版を固定する

この段のコマンドは、時間と条件に当たらない環境か、作り直した環境で流します。当たったかもしれない環境では、流しません(Python の起動になるためです)。

pip install litellm==1.106.2
pip freeze > requirements.txt

== で決まった版を求めるのが、pip の文書の言う「固定」です。pip freeze も、当たらない環境か作り直した環境で流します。これで、直接入れたものだけでなく、依存(その部品が使う部品)もすべて固定した requirements のファイルが作れます。>= のような下限だけの書き方は、固定ではありません。

pip の文書は、ハッシュ(部品の中身から計算した識別の文字列)も付けて固定すると、PyPI や HTTPS の証明書の連なりが乗っ取られた場合にも守れる、と書いています。今回の件でハッシュが何を防いだかは、この記事では言いません。

Docker はダイジェストで固定する

Docker の文書によると、タグで取ると、取り直すたびに新しい版になりうるのに対し、ダイジェストで取ると、その版に「固定」でき、いつも同じイメージを使えます。

報告者は、10月21日の時点で、タグではなくダイジェストで v1.106.2 に固定するよう勧めています。これは報告者の勧めで、LiteLLM の告知の文ではありません。疑わしいイメージは、ここでも起動しません。

uv で入れている人

uv.lock で版を固定する話は、uv の記事にあります。この記事で、新しいコマンドは足しません。ここでも、時間と条件に当たらない環境か、作り直した環境で行います。

被害と公的機関の告知は?(2026年10月23日時点)

入れた人の数や、被害の件数は、告知にも LiteLLM の担当者の書き込みにも、見つかりませんでした。告知は、外のネットにつながる機械に入れたなら、送り出しは成功したと考えるよう書いています。

公的機関の一覧は、2026年10月23日の16時56分から17時7分ごろ(日本時間)に見た範囲では、次のとおりです。

出どころ見たこと
CISA(アメリカの政府機関)の告知とニュースの一覧LiteLLM の 1.107.0 の件はありません。KEV(悪用が確認された脆弱性の一覧)には LiteLLM が 3 件ありますが、どれも前の別の脆弱性です。この件は CVE が無い件です
JPCERT/CC(日本のセキュリティの情報を扱う組織)の注意喚起と Weekly Report の一覧LiteLLM は載っていません(Weekly Report のいちばん新しいのは10月21日号)
IPA(情報処理推進機構)の注意喚起の一覧LiteLLM は載っていません
LiteLLM のリポジトリの Security Advisory(脆弱性の告知)この件のものはありません。いちばん新しいのは、10月1日公開の別の件です

KEV に無いことや、一覧に載っていないことは、被害が無い証明ではありません(脆弱性の知らせの読み方に、同じ読み方を書きました)。

告知は、次の更新を「22:30 UTC」(日本時間の10月22日 7時30分)と書いたまま、20:30 UTC の版のままです。担当者は、issue に、10月22日の11時19分に、2 時間ごとの更新をやめ、大きな進展があったときに書く形に変えた、と書いています。

よくある質問

新しい版に上げればいいですか?

上げる先の版が、ありません。「1.107.1 以上へ」と書いた記事を見かけるかもしれませんが、PyPI に 1.107.1 はありません(2026年10月23日時点)。告知が勧めるのは、「当面は、1.106.2 か、この告知の時点より前に出た版に、番号を決めて固定してください」です(→「当たっていなくても:版を固定する」)。

ほかの記事で、Python のコマンドで版を見る方法を見ました。先にそれをしてもいいですか?

その方法は、告知にも載っています。ただ、同じ告知が、当たった環境では、pip を含めて Python を起動すると、仕組みがまた動く、とも書いています。Python の文書も、.pth の import の行は、起動のたびに動くと書いています。当たった可能性のある環境では、先にファイルを探します(→「どうやって確かめる? Python を動かす前にファイルを探す」)。

LiteLLM を自分で入れた覚えがありません。関係ありますか?

関係あることがあります。自分で入れていなくても、ほかの部品の依存として入ることがあります。pip の文書は、requirements のファイルの固定が、直接入れたものだけでなく、依存の依存(transitive dependencies)にも及ぶ、と書いています。探し方は同じです。dist-info の名前を探します(→「探す3つのファイル」)。

LiteLLM の文書にある docker.litellm.ai のイメージを使っていました。当たりますか?

LiteLLM の文書の Docker の始め方は、この名前を使っています。告知は、この名前を書いていません。悪いイメージが出ていた時間に、この名前で悪いイメージが配られたかは、確かめられませんでした。いまは、GHCR と同じものを返します(手元で確かめました)。当たる・当たらないを決めず、イメージを起動せずに、ダイジェストを告知の値と比べてください(→「Docker:イメージを起動せず、ダイジェストを告知と比べる」)。

1.106.2 より古い版に固定してもいいですか?

この記事では言えません。告知は、それより前の版は安全と書いています。一方、3月の 1.82.7・1.82.8 は、GitHub のデータベースと OSV に悪い版として載っています(いま PyPI にありません)。古い版には、別の脆弱性もあります(KEV には LiteLLM の別の件が 3 件あります)。告知が名指しするのは、1.106.2 です(→「いまの版は 1.106.2(直った新しい版は出ていない)」)。

自分の環境で確かめること(チェックリスト)
  • 10月21日の20時39分〜22時23分(日本時間)に、版を固定せずに LiteLLM を入れた操作があったか、記録の時刻で見る(→「pip で入れた人」)
  • CI は、実行の一覧の時刻で見る(Docker のイメージを使う CI は20時46分〜23時20分)(→「CI で入れた人」)
  • Docker は、v1.107.0・latest・main-latest・main-stable を、20時46分〜23時20分に使ったか見る(→「Docker のイメージを使った人」)
  • 疑わしい環境では Python を動かさず、litellm-1.107.0.dist-info・cook.pth・部品の置き場(site-packages など)のすぐ下の sitecustomize.py を探す(→「探す3つのファイル」「Mac・Linux で探す」)
  • Docker は、イメージを起動せず、ダイジェストを告知の値と比べる(→「Docker:イメージを起動せず、ダイジェストを告知と比べる」)
  • 当たったなら、告知の手順で消し、作り直し、鍵を替える(→「入っていたら、何をする? 告知の手順」「替える鍵(告知が名指しするもの)」)
  • LiteLLM を使い続けるなら、当たっていなくても、当たらない環境か作り直した環境で、litellm==1.106.2 に固定する(→「当たっていなくても:版を固定する」)

まとめ

  • 2026年10月21日、LiteLLM 1.107.0 に、資格情報を盗む仕組みが入って、PyPI と Docker の登録所に配られた。ソフトの弱点ではなく、悪い版そのものが配られた件。CVE の番号は付いていない(2026年10月23日時点)
  • 当たるのは、10月21日の20時39分〜22時23分(日本時間)に版を固定せずに pip で入れた人と、20時46分〜23時20分に 4 つのタグのイメージを使った人。それより前の版は安全と告知は書く
  • 確かめるときは、疑わしい環境で Python を動かさない。ファイルの上で、告知の 3 つを探す。Docker はイメージを起動せず、ダイジェストを告知の値と比べる
  • 入っていたら、乗っ取られたものとして扱う。告知の手順でファイルを消し、環境を作り直し、その機械から届く鍵を全部替える
  • LiteLLM を使い続けるなら、当たっていなくても、当たらない環境か作り直した環境で、1.106.2 に固定する。直った新しい版は出ていない
  • 公的機関(CISA・JPCERT/CC・IPA)の一覧に、この件は見つからなかった。ただし、載っていないことは、被害が無い証明ではない
  • この記事で確かめていないこと:
    • docker.litellm.ai で、悪いイメージが出ていた時間の中身
    • uv や Poetry で入れた人が当たるか
    • Docker のイメージの中に litellm-1.107.0.dist-info があるか
    • pip や uv のキャッシュに 1.107.0 が残ったときのこと
    • Ubuntu のパッケージの一覧での sitecustomize.py の場所(手元の Ubuntu 24.04 で見た 1 つだけ)
    • Windows での動き、conda の Python、containerd の保存の形の Docker
    • 入れた人の数、1.106.2 より古い版の安全さ

参考資料

この記事の内容は、冒頭に書いた日時に開いた文書をもとにしています。告知や公的機関の一覧は、更新されることがあります。

※この記事は、2026年10月23日時点の公式の資料と照らして確かめています。誤りに気づいたらお問い合わせからお知らせください。

PR
PR
タイトルとURLをコピーしました