2026年10月21日、AIアプリ作りでよく使われる部品「LiteLLM」に、不正な中身を仕込んだ版が配られました。版の番号は1.107.0。LiteLLMは3月にも同じ被害に遭っていて、今年2度目です。

使っている部品を経由して入り込む手口を、サプライチェーン攻撃と呼びます。仕入れた原材料に異物が混ざるようなものです。LiteLLMのサプライチェーン攻撃は、なぜ同じ部品で2度も起きたのか。その問いから出発します。

LiteLLMは何をする部品か

LiteLLMは、Claude、GPT、Geminiなど、会社ごとに違うAIの呼び出し方を1つの書き方にそろえてくれる部品です。Python(プログラミング言語の1つ)で書かれていて、無料で公開されています。

使い方は、プログラムに組み込む方法と、「プロキシ」(社内の全員のAI利用を1か所で中継する窓口)として立てる方法の2つ。後者では、各社のAPIキー(AIを使うための合言葉)をLiteLLMにまとめて預けます。

Claude Codeも、こうした会社の中継窓口(LLMゲートウェイ)を通して使う設定ができます。その窓口にLiteLLMを選んでいる会社もあるので、Claude Codeしか使っていないつもりでも、裏でLiteLLMが動いていることがあります。

10月21日に何が起きたか

Pythonの部品を配る公式の置き場「PyPI」に、LiteLLMの1.107.0が載りました。同じ中身は、LiteLLMを丸ごと動かせる配布用のイメージ(Docker、動かすのに必要なもの一式を詰めた箱)にも入り、latest や main-stable という名前でも配られていました。版を指定していなかった人ほど受け取りやすい状態でした。

LiteLLMの事故報告によると、PyPIに載っていたのは日本時間の20時39分から22時23分までの約1時間40分、Dockerのほうは23時20分ごろまでです。

短い時間でも、自動で部品を入れ直す仕組み(CI)は夜中も動いています。

何が盗まれる仕組みだったのか

不正な版は、cook.pth、cook.py、sitecustomize.py という3つのファイルを足していました。どれも、Pythonが起動するたびに自動で読み込まれる種類のファイルです。

ここが厄介な点です。LiteLLMを使うプログラムを動かしたときだけでなく、同じ「Pythonの環境」(Pythonと部品一式をまとめた作業場。1台のパソコンに複数作れる)でPythonが起動するたび、たとえば部品を管理する道具 pip を使っただけでも、盗む処理が走ります。

狙われたのは、SSHの鍵(サーバーに入るための鍵)、クラウドのログイン情報、AI各社のAPIキーなど。プロキシなら、預けていたキーの一覧もまとめて対象です。

調べてわかった「2度狙われた理由」

3月の件は、開発側が使っていた別の検査ツールが先に乗っ取られ、そこから部品を公開するための合言葉が盗まれたのが原因でした。10月の件は、社内の記録(ログ)に残っていたGitHubの認証情報で、公開の手順が書き換えられたと報告されています。最初にどこから入られたかは、Microsoftの分析でも特定されていません。

入口は違っても、共通しているのは「公開する仕組みそのもの」が破られた点です。

そのうえで、筆者が一番大きいと考える理由は、LiteLLMが「鍵束」だということです。各社のAPIキーを1か所に集める道具なので、ここを1回破れば何社分もの鍵が一度に手に入る。便利な集約点ほど狙われる。LiteLLMのサプライチェーン攻撃は、そのわかりやすい実例です。

自分の環境に入っていないか確かめる

ここで大事な注意があります。疑いのある環境では、Pythonも pip も動かさないでください。版を確かめようと pip show litellm を打つと、その瞬間に盗む処理が走ります。Microsoftもこの点をはっきり書いています。

代わりに、ファイルを探すだけの find を使います。

# 入っているLiteLLMの版をファイル名から探す(Pythonは起動しない)
find / -path '*site-packages/litellm-*.dist-info' -maxdepth 8 2>/dev/null

# 不正なファイルが置かれていないか
find / \( -name cook.pth -o -name cook.py \) -path '*site-packages*' 2>/dev/null

1つ目で litellm-1.107.0.dist-info が出たら要対応です。sitecustomize.py は正規に置かれている環境もあるので、見つかったら中身を確かめます。Dockerで動かしている場合は、10月21日の夜に latest などの名前で取り込んでいないかを確認します。

筆者も研修のデモ用サーバーでLiteLLMを動かしていたので、22日の朝に確かめました。結果は1.104系で、今回の版ではありませんでした。ただ、確認の途中でPythonの環境が3つに分かれていて、どれで動いているのか自分でも把握できていなかったことに気づきました。実は最初、うっかり pip show を打ちかけて手を止めています。まず棚卸しが要る、というのが一番の学びです。

Claude Codeに頼むなら「pythonやpipは実行せず、findでファイルを探すだけにして」と最初に伝えてください。読むだけで点検を任せる頼み方は、別の記事で紹介しています。

コマンドを打てない人は、社内のエンジニアや外注先に「LiteLLMを使っていますか、1.107.0は入っていませんか」と聞くだけでも十分な一歩です。

1.107.0が入っていたら

やることは次の順です。

  1. 環境ごと作り直す。入れ直すだけでは、起動時に読まれるファイルが残ることがある
  2. 版を1.106.2に固定する(勝手に新しい版へ上がらないよう番号を決め打ちする)
  3. その環境から見えていたAPIキー、クラウドの鍵、SSHの鍵をすべて作り直す
  4. ログイン中の状態も切る。鍵を変えても、すでに発行された通行証(ログイン状態を保つ情報)が生きている場合がある

残った疑問

版を固定しておけば防げたのか、というと半分だけです。受け取ったのは latest に任せていた人たちなので、固定は効きます。

一方で、固定した版をいつかは上げる日が来ます。今回の不正な版は、公式の置き場から配られ、見た目では本物と区別がつきませんでした。新しい版を数日待ってから取り込む運用まで決めている小さな会社は、筆者の周りではまだ少数です。部品の更新を誰がいつ判断するのかは、AIアプリを作る側に回るなら避けて通れない問いです。

10月に起きたほかのセキュリティ事案は、月のまとめに整理しています。