テクノロジーインサイト一覧へ戻る
2026.08.20

crates.io の arrayref など3クレートが一時汚染、cargo build だけで遠隔コード実行——RUSTSEC-2026-0260 とブロックチェーン基盤への影響範囲

crates.io の arrayref など3クレートが一時汚染、cargo build だけで遠隔コード実行——RUSTSEC-2026-0260 とブロックチェーン基盤への影響範囲

何が起きたか

Rust Security Response Team は、2026年8月20日に crates.io へ公開された arrayref 0.3.10、internment 0.8.7、append-only-vec 0.1.9 の3バージョンを削除し、当該メンテナのアカウントを予防的にロックした。3クレートはいずれも同一の所有者アカウントから公開されており、Rust側は当該メンテナ本人による悪意ある行為ではなく、開発端末または crates.io の公開資格情報の侵害が原因と見ている。勧告は RUSTSEC-2026-0260 として発行され、初期版の記述は後日更新されている。

3つの正規クレートに共通して追加されていたのが、proc-macro1 という依存だった。これは広く使われる proc-macro2 に酷似した名前の、攻撃者が用意したクレートである。悪意あるコードは proc-macro1 側のビルドスクリプト(build.rs)に置かれており、依存解決がこのバージョンに当たった状態でビルドを走らせるだけで実行された。セキュリティ企業 Socket の分析によれば、同社のスキャナが proc-macro1 を検知したのは同日07時29分50秒(UTC)で、その時点では arrayref 0.3.10 のみが公開済みであり、残る2件は数分後に続いた。悪意あるバージョンが公開されていた時間は、各パッケージあたりおよそ86分から107分と報告されている。StepSecurity は一連のキャンペーン全体の露出時間帯を同日07時11分から09時25分(UTC)、すなわち2時間14分と整理している。

攻撃者は proc-macro1 と同じビルドスクリプトを持つ proc-macro-en も用意しており、片方が削除されても campaign が止まらない構成になっていた。さらに aovine、arone、aronenao、tinymember といった攻撃者所有のクレートが同時に削除されている。arone と aronenao は攻撃の2日前(8月18日)に公開されており、Socket はこれらを準備段階の資産と評価している。加えて攻撃者は arrayref の一部の正規旧バージョンを yank(取り下げ)しており、新規の依存解決を悪意ある 0.3.10 へ誘導しようとした形跡がある。正規バージョンはその後 Rust 側により復旧された。

なぜブロックチェーン基盤に効くのか

arrayref は配列変換の小さなユーティリティで、累計ダウンロードはおよそ2億4,500万回と報告されている(公開直前時点を1億5,200万回とする報道もあり、集計時点によって数字が異なる)。問題は使われている場所である。arrayref は blake3 や winit などの下層に位置し、Solana および Ethereum のツールチェーンの依存グラフにも入っている。ウォレット、バリデータ、インデクサ、DeFiのフロントエンドといった、鍵や署名資材に近い場所でビルドが走るプロジェクト群が、直接依存としてではなく推移的依存として影響範囲に入った。

技術的な急所は build.rs の位置づけにある。Cargo のビルドスクリプトは、コード生成やCバインディングのために「ビルド時に任意のコードを実行してよい」仕組みとして設計されている。つまり、依存先の関数をアプリケーションが一度も呼ばなくても、依存解決さえ通ればコンパイルの過程で実行される。実行環境はCIランナーや開発端末であり、そこには署名鍵、レジストリのトークン、クラウド資格情報が置かれていることが多い。報告されているペイロードは、base64断片からC2アドレスを組み立て、TLS検証を常に成功させる独自の証明書検証器を差し込む挙動を含む。監査でありがちな「本番バイナリに悪意あるコードが入ったか」という問いは、この攻撃では的を外している。狙われたのはビルドする側の環境そのものだった。

同種の事例は npm の postinstall フックや PyPI の setup.py で繰り返されてきたが、Rust では build.rs が言語仕様として正当な拡張点である分、「怪しいスクリプトの混入」として検出しにくい。ビルドスクリプトを持つクレートはごく普通に存在し、その存在自体が異常シグナルにならない。ここは設計上のトレードオフであり、短期的に塞げる種類の穴ではないと考えられる。

検出の経緯も参考になる。Socket は自社のスキャナが proc-macro1 を自動検知し、その後の分析で範囲の広がりを確認したと説明している。別途、Nextron Systems の研究者が Rust Security Response Team へ報告し、技術的詳細は RustSec を通じて開示された。SlowMist、Socket、StepSecurity といった複数のセキュリティ企業が並行して報告している構図で、単一の窓口に依存しない検知が働いた事例といえる。一方で、これらはいずれも公開直後の検知であり、実際にペイロードが実行された環境の特定は各組織のログに委ねられている。RustSec の初期版勧告には「利用の証跡は確認されていない」旨の記述があったが、これは公開ダウンロード統計と外部報告の不在に基づく評価であり、後に表現が更新されている。この「初期評価とその後の修正」という経過自体が、勧告を一度読んで終わりにしてはいけないことを示している。

想定される落とし穴

第一に、レジストリからの削除はローカルの汚染を消さない。悪意あるバージョンが解決された Cargo.lock、~/.cargo/registry のキャッシュ、ビルド済みのコンテナイメージ、CIのレイヤーキャッシュは、削除後もそのまま残る。cargo update を実行しても、ロックファイルが上書きされるだけで、既に実行されたペイロードの痕跡は消えない。

第二に、直接依存だけを見ても分からない。arrayref は多くのプロジェクトで推移的依存であり、Cargo.toml には現れない。確認すべきは Cargo.lock と、CIの当該時間帯のビルドログである。

第三に、正規バージョンの yank が依存解決を動かす。攻撃者は arrayref の一部の旧バージョンを取り下げており、バージョン範囲指定で依存を書いているプロジェクトの解決結果が、意図せず悪意ある新版へ寄せられうる状態を作っていた。ロックファイルを固定していれば影響を受けないが、CIで毎回解決し直す構成や、ロックファイルをコミットしない運用のライブラリ側プロジェクトは、この誘導を直接受ける。「ロックファイルをコミットするのはアプリケーションだけでよい」という慣行は、この観点では見直しの余地がある。

第四に、露出時間帯が短いことが安全の根拠にならない。監査結果が「利用の証跡なし」であっても、それは公開ダウンロード統計から見た評価であり、特定組織のCIが当該2時間強にビルドを走らせていないことを証明するものではない。判断材料は自社のログ側にある。

【技術インサイトとアクション】

  1. パッケージレジストリの削除対応は「配布の停止」であって「汚染の除去」ではない。上流が対応したという事実は、自社のロックファイル・キャッシュ・イメージが清浄であることを一切保証しない。同じ構図は npm、PyPI、コンテナレジストリでもそのまま成り立つ。 [ノード運用者・インフラ担当] 今週中に、Cargo.lock を対象の3バージョンで全リポジトリ横断検索し、2026年8月20日07時から10時(UTC)のCIビルドログと外向き通信を確認する。該当があれば当該ランナーの資格情報をローテーションする。
  2. ビルド時実行を許す仕組み(Cargo の build.rs、npm の postinstall など)を持つ言語では、依存の「使用」ではなく「解決」が攻撃面になる。呼び出していないから安全という前提は成り立たない。 [コントラクト開発者・ツール保守者] 次回リリースまでに、CIビルドを外向き通信を遮断したネットワークで実行する構成へ切り替え、--locked / --offline を既定にしてロックファイル外の解決を禁止する。
  3. 単一メンテナのアカウントが、依存グラフの下層で数百のプロジェクトに対する書き込み権限と同義になっている。これは特定クレートの問題ではなく、暗号資産インフラが共有レジストリに依存している構造そのものの問題である。 [プロダクト側・セキュリティ責任者] 四半期内に、鍵・署名資材を扱うビルドを一般開発用CIから分離し、依存の追加・更新に人手のレビューを必須とする内部ミラーの導入を検討する。

【引用:出典】

本記事は公開情報に基づく技術解説であり、投資助言を目的としたものではありません。