Skip to content

サプライチェーン攻撃を成立させないための対策(クライアント編)

サプライチェーン攻撃の文脈では、ソーシャルハッキングなどで侵害される側の視点もあるが、ここでは利用しているモジュールで侵害された悪性バージョンが公開されたものとして、どう対策をするかについて考える。ここではクライアントでの対策を挙げるが、サプライチェーン攻撃を成立させないための対策(リポジトリ編)もある。

2026年当初から、NPMパッケージへのサプライチェーン攻撃が広範囲に展開されている。他のパッケージよりNPMに偏っているのはいくつか理由がある。

  • バージョン指定で @^1.1.0 のように自動更新される機会がある
  • インストールのとき postinstall フックでコードを実行することができる
  • 細かいパッケージが多い

細かいパッケージの話はどうしようもないが、それ以外は対策ができるのでやっておく。

公開直後のバージョンは避ける

Section titled “公開直後のバージョンは避ける”

Dependabotにcooldownを設定するでも書いたが、公開されてすぐに発覚する検体が多いので、完全ではないが一定期間を置けば安全だと判断しても良いだろう。日数は宗派があると思うけれどRussの例では7日だったので、そのくらいでいいんじゃないだろうか。

脆弱性の修正を除けば、そもそも急いでアップデートしなければならない事情なんてそんなに多くはない。

例えば即席のスクリプトで go run module@latest のように latest を指定することがあるけれど、これだと悪性バージョンの入り込む余地が存在する。開発で使うツールなどは go tool にしておいて、バージョンは go.mod で管理するのが良いだろう。

一応 pkgsite 側で対応が実装されていて、GOPROXY 環境変数に /delay/7d のようなパラメータを与えると公開を遅らせることができる仕様になるらしいので、リリースされたら go run を素朴に使ってもいいかもしれない。

強い権限があるものを git-credential-xxx で参照したり、gh auth コマンドで出力したりできてしまう。Russの投稿でも言及されている。

On the topic of tokens, it is very wrong that a project on GitHub or NPM can insist on 2FA for people logging in, but then those same systems allow using these short easily stolen strings as 1FA methods with equivalent power. Recent attacks demonstrate the significant lateral movement this enables.

また、トークンは盗まれてしまえばそのまま使うことが可能だけど、SSH鍵であれば暗号化しておけば盗まれてもある程度は耐性があるので、通常はSSH経由でリポジトリを操作する。鍵についてはSSH鍵の運用設計で定めたように運用する。

環境変数にシークレットを残さない

Section titled “環境変数にシークレットを残さない”

Dockerだろうがローカルだろうが、環境変数は適切な権限があれば読めてしまうので残してはいけない。

VS CodeやObsidianなど独自のプラグインシステムを持つアプリケーションもある。これらもNPMパッケージに依存しているので、なるべく安全な場所で実行したい。これの手段としては、Flatpakでファイルシステム参照を制限する方法のように隔離すればいい。

安全にビルドやローカル実行したい場合はどうするか。これもDocker化するとか、Flatpakイメージをビルドするなどの方法はあるが、面倒すぎて維持できる気がしない。リリースからインストールまでを遅延させているし、仮に汚染されたパッケージが実行されても鍵は暗号化しているので良しとする。

ダウンロードと同時に実行しない

Section titled “ダウンロードと同時に実行しない”

それは困るという話はあるが、そもそもこいつがなければここまで悪化していないだろう。