LiteLLMのリリースノートを眺めていたら、v1.86.5のchangelogにcosignを使ったDocker image verificationの話が載っていた。正直ここまでちゃんと読んだことなかったけど、今回は少し気になって手を動かしてみた。
うちのチームはLiteLLMをProxyとして使っていて、複数のLLM APIをラップして社内のサービスから叩く構成にしている。OpenAIのAPIキーとAnthropicのAPIキーを環境変数で渡して、model名でルーティングするやつ。便利なんだが、Dockerイメージをそのままpullして使っていて、署名の検証とか一切やってなかった。それがちょっと頭の片隅にひっかかってた。
リリースノートによると、LiteLLMのDockerイメージはすべてcosignで署名されていて、commit `0112e53` で導入した同じ鍵を使い続けているらしい。検証方法は2種類あって、commit hashをpinする方法と、release tagを使う方法。推奨はcommit hash側で、「cryptographically immutable」という理由がそのまま書いてある。tagはprotectedとはいえmutableなので納得感はある。
実際に自分の手元で動かしてみたコマンドはこれ:
出力にはこんな感じのメッセージが出てくる。
ハマったのはcosignのインストールまわりで、brewで入れたらパスが通ってなくて一瞬「コマンドが見つからん」ってなった。あるある過ぎる。
LiteLLMはGitHubで50k starを超えているリポジトリで、うちみたいな小さいスタートアップから大きめの会社まで幅広く使われている。それだけ使われているとサプライチェーン攻撃のターゲットになりやすい、という話はSolarwindsのあれ以来リアルに意識するようになった。
悪意のある人がDockerHub系のレジストリに同名の偽イメージをpushする、みたいなことは理論上ありえる。cosignの署名検証をCIに組み込んでおけば、そこを防ぎやすくなる。今うちのCI/CDはGitHub ActionsでDockerイメージをpullしてからdeployまで繋げているので、deployのstepの前にcosign verifyを挟むのが自然な形だと思った。
実装コストはそんなに高くない。cosignをGitHub Actionsのstepで入れる方法はいくつかあって、`sigstore/cosign-installer`というofficial actionがあるので、それを使うのが一番楽そうだ。彼女に「最近なんか勉強してるの?」って聞かれて「Dockerイメージの署名検証」って答えたら「意味わからん」って言われた。まあそういうもんだ。
話を戻すと、今回のv1.86.5は機能追加というよりstable/1.86.x系へのバックポートがメインで、#30064・#29991・#30009 の3つのPRがまとめて取り込まれている。セキュリティ面のリリースノートが丁寧に書かれているのは、LiteLLMがproduction用途で使われているという意識を開発チームが持っている証拠だと個人的には感じた。
とりあえず今日のところは手元で動かすところまでは確認できた。次にやることを整理すると:
週明けにチームのSlackに「Dockerイメージの署名検証入れよう」って投げてみようと思う。セキュリティ系の提案って通りにくいことも多いけど、手順が単純で影響範囲が明確なやつは割とすんなり通る印象がある。
自分でライブラリを選定するときに「メンテが続いているか」「release noteにセキュリティ周りの記述があるか」を見るようにしているが、LiteLLMはそこが安心できる。50kスターがあるから信用するというより、こういうリリースノートの書き方を見てから信用するかを判断する。
つまり、リリースノートはちゃんと読んだほうがいい。
うちのチームはLiteLLMをProxyとして使っていて、複数のLLM APIをラップして社内のサービスから叩く構成にしている。OpenAIのAPIキーとAnthropicのAPIキーを環境変数で渡して、model名でルーティングするやつ。便利なんだが、Dockerイメージをそのままpullして使っていて、署名の検証とか一切やってなかった。それがちょっと頭の片隅にひっかかってた。
cosignでイメージを検証する、というのが今回の本題
リリースノートによると、LiteLLMのDockerイメージはすべてcosignで署名されていて、commit `0112e53` で導入した同じ鍵を使い続けているらしい。検証方法は2種類あって、commit hashをpinする方法と、release tagを使う方法。推奨はcommit hash側で、「cryptographically immutable」という理由がそのまま書いてある。tagはprotectedとはいえmutableなので納得感はある。
実際に自分の手元で動かしてみたコマンドはこれ:
cosign verify \
--key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \
ghcr.io/berriai/litellm:v1.86.5出力にはこんな感じのメッセージが出てくる。
The following checks were performed on each of these signatures:
- The cosign claims were validated
- The signatures were verified against the specified public keyハマったのはcosignのインストールまわりで、brewで入れたらパスが通ってなくて一瞬「コマンドが見つからん」ってなった。あるある過ぎる。
SupplyChain攻撃の話、今の自分たちの構成で考えてみた
LiteLLMはGitHubで50k starを超えているリポジトリで、うちみたいな小さいスタートアップから大きめの会社まで幅広く使われている。それだけ使われているとサプライチェーン攻撃のターゲットになりやすい、という話はSolarwindsのあれ以来リアルに意識するようになった。
悪意のある人がDockerHub系のレジストリに同名の偽イメージをpushする、みたいなことは理論上ありえる。cosignの署名検証をCIに組み込んでおけば、そこを防ぎやすくなる。今うちのCI/CDはGitHub ActionsでDockerイメージをpullしてからdeployまで繋げているので、deployのstepの前にcosign verifyを挟むのが自然な形だと思った。
実装コストはそんなに高くない。cosignをGitHub Actionsのstepで入れる方法はいくつかあって、`sigstore/cosign-installer`というofficial actionがあるので、それを使うのが一番楽そうだ。彼女に「最近なんか勉強してるの?」って聞かれて「Dockerイメージの署名検証」って答えたら「意味わからん」って言われた。まあそういうもんだ。
話を戻すと、今回のv1.86.5は機能追加というよりstable/1.86.x系へのバックポートがメインで、#30064・#29991・#30009 の3つのPRがまとめて取り込まれている。セキュリティ面のリリースノートが丁寧に書かれているのは、LiteLLMがproduction用途で使われているという意識を開発チームが持っている証拠だと個人的には感じた。
自分のCIに入れるまでの残タスクを整理する
とりあえず今日のところは手元で動かすところまでは確認できた。次にやることを整理すると:
- GitHub Actionsに `sigstore/cosign-installer` を追加する
- deploy step の前に `cosign verify` を挟む
- commit hashをpinした公開鍵のURLをCIの環境変数に切り出しておく
- verificationが失敗したときにdeployが止まることをローカルで確認する
週明けにチームのSlackに「Dockerイメージの署名検証入れよう」って投げてみようと思う。セキュリティ系の提案って通りにくいことも多いけど、手順が単純で影響範囲が明確なやつは割とすんなり通る印象がある。
自分でライブラリを選定するときに「メンテが続いているか」「release noteにセキュリティ周りの記述があるか」を見るようにしているが、LiteLLMはそこが安心できる。50kスターがあるから信用するというより、こういうリリースノートの書き方を見てから信用するかを判断する。
つまり、リリースノートはちゃんと読んだほうがいい。