pnpm でサプライチェーン攻撃に備える
インフラ
npm エコシステムでは、正規のパッケージ名で悪意あるバージョンが公開される「サプライチェーン攻撃」が繰り返し起きている。個人ブログのような小さなプロジェクトでも、依存関係の数は数百に及ぶので他人事ではない。ここでは pnpm でできる対策をまとめる。
エイジゲート: minimumReleaseAge
もっとも効果が大きいのがこれだ。「公開されてから一定時間が経っていないバージョンはインストールしない」という設定で、悪意あるバージョンが検出・削除されるまでの猶予を稼げる。
# pnpm-workspace.yaml
minimumReleaseAge: 4320 # 分単位 = 3日3日にしているのには理由がある。攻撃バージョンが金曜の夜に公開されると、週末を挟んで検出が遅れる。3日あればその週末をまたげる。
非レジストリ依存をブロック: blockExoticSubdeps
推移的な依存が git リポジトリや tarball の URL を直接指すのを禁止する。すべての依存をレジストリ経由に限定できる。
blockExoticSubdeps: true信頼レベルの低下を検知: trustPolicy
パッケージの発行元の信頼レベルが以前より下がった場合(乗っ取りの兆候)にインストールを止める。
trustPolicy: no-downgradepostinstall スクリプトを絞る: allowBuilds
pnpm はデフォルトで依存の postinstall スクリプトを実行しない。ビルドが必要なパッケージだけを明示的に許可する。
allowBuilds:
esbuild: trueこうしておくと、これまでビルドを必要としなかったパッケージが、ある日突然スクリプトを実行し始めても気づける。
ロックファイルは必ずコミット
pnpm-lock.yaml をコミットしておけば、CI 環境(CI=true)では pnpm が自動で frozen install を行う。加えて package.json の packageManager フィールドで pnpm 自体のバージョンも固定しておくと安心だ。
新しい依存を足してポリシーに引っかかったら、minimumReleaseAge を緩めるのではなく pnpm clean --lockfile && pnpm install でロックファイルを作り直すのが正しい対処になる。


