最近チームで LiteLLM を Proxy として使い始めた。複数の LLM を一つのエンドポイントで扱えるのが便利で、OpenAI / Anthropic / Gemini を切り替えながらコストを比較する用途にえぐいくらいハマっている。
そこに v1.88.3 のリリースノートが流れてきた。主な変更は stable/1.88.x へのバックポートだけで、機能追加はほぼない。ただ、リリースノートの冒頭にある Docker image の署名検証の説明がちゃんと整備されていて、「あ、これまだ自分の手元で確認してなかったな」と気づいた。
LiteLLM の Docker image は cosign で署名されていて、署名に使ったキーはコミット 0112e53 で導入されたものに統一されている。検証方法は 2 通り紹介されている。
リリースノートに「commit hash は cryptographically immutable だから strongest」と書いてあって、確かにそうだと思った。tag は force push で上書きできる場合があるし、supply chain 攻撃の文脈でそこを突かれると怖い。実際に verify するコマンドはこれだ。
ローカルで試すと、cosign claims were validated と signatures were verified の 2 行が返ってきた。ちゃんと通る。
うちのチームは Compose で LiteLLM を立ち上げていて、image の digest を固定してはいるものの署名の verify は CI に組み込んでいなかった。正直「OSS だし BerriAI が出してるやつだから大丈夫でしょ」でスルーしていた。
最近 LLM 周りのサービスは API キーや社内データが通ることが多い。LiteLLM Proxy の場合、各モデルへの API key を config に書いておくケースが多いから、image が差し替えられていたら最悪 key が漏洩する。「ハマったときに気づく前に一回刺さる」パターンが怖い。
彼女に「なんかずっと GitHub 見てるね」と言われたので「image の signature 検証してる」と答えたら「それ仕事?」と返された。個人の Docker 環境で動かしてる趣味プロダクトの話をしていたので、まあそうかもしれない。
ただ実際、個人開発でも LLM の API key を proxy に渡して動かすなら対象は同じだ。趣味プロダクトだから雑でいい、という話にはならない。
チームの話に戻ると、CI で pull 前に verify を走らせる構成を組む方向で動くことにした。GitHub Actions だと cosign の action が公式に用意されているので、image digest と公開鍵の URL を渡すだけで動く。
LiteLLM は Stars が 50.8k を超えていて、フォークも 9k に達している。これだけ使われているライブラリになると supply chain の攻撃面として意識される規模でもある。署名の仕組みが v1.88.3 のリリースノートで丁寧に案内されているのは、そういうことを分かって整備してくれているんだと読んだ。
バックポートだけのマイナーリリースでも、こういう細かい部分を確認するきっかけになる。次の image pull の前に verify を一度手元で通してから、CI に組み込む PR を出す。
そこに v1.88.3 のリリースノートが流れてきた。主な変更は stable/1.88.x へのバックポートだけで、機能追加はほぼない。ただ、リリースノートの冒頭にある Docker image の署名検証の説明がちゃんと整備されていて、「あ、これまだ自分の手元で確認してなかったな」と気づいた。
cosign でどう検証するか
LiteLLM の Docker image は cosign で署名されていて、署名に使ったキーはコミット 0112e53 で導入されたものに統一されている。検証方法は 2 通り紹介されている。
- commit hash を pinして検証する方法 (推奨)
- release tag を使う方法 (手軽だが tag protection に依存)
リリースノートに「commit hash は cryptographically immutable だから strongest」と書いてあって、確かにそうだと思った。tag は force push で上書きできる場合があるし、supply chain 攻撃の文脈でそこを突かれると怖い。実際に verify するコマンドはこれだ。
cosign verify \\
--key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \\
ghcr.io/berriai/litellm:v1.88.3ローカルで試すと、cosign claims were validated と signatures were verified の 2 行が返ってきた。ちゃんと通る。
「とりあえず動かしてるだけ」のやばさ
うちのチームは Compose で LiteLLM を立ち上げていて、image の digest を固定してはいるものの署名の verify は CI に組み込んでいなかった。正直「OSS だし BerriAI が出してるやつだから大丈夫でしょ」でスルーしていた。
最近 LLM 周りのサービスは API キーや社内データが通ることが多い。LiteLLM Proxy の場合、各モデルへの API key を config に書いておくケースが多いから、image が差し替えられていたら最悪 key が漏洩する。「ハマったときに気づく前に一回刺さる」パターンが怖い。
彼女に「なんかずっと GitHub 見てるね」と言われたので「image の signature 検証してる」と答えたら「それ仕事?」と返された。個人の Docker 環境で動かしてる趣味プロダクトの話をしていたので、まあそうかもしれない。
ただ実際、個人開発でも LLM の API key を proxy に渡して動かすなら対象は同じだ。趣味プロダクトだから雑でいい、という話にはならない。
CI に verify を入れるとしたら
チームの話に戻ると、CI で pull 前に verify を走らせる構成を組む方向で動くことにした。GitHub Actions だと cosign の action が公式に用意されているので、image digest と公開鍵の URL を渡すだけで動く。
LiteLLM は Stars が 50.8k を超えていて、フォークも 9k に達している。これだけ使われているライブラリになると supply chain の攻撃面として意識される規模でもある。署名の仕組みが v1.88.3 のリリースノートで丁寧に案内されているのは、そういうことを分かって整備してくれているんだと読んだ。
バックポートだけのマイナーリリースでも、こういう細かい部分を確認するきっかけになる。次の image pull の前に verify を一度手元で通してから、CI に組み込む PR を出す。