はじめに
2026年3月31日、npmパッケージ「axios」がサプライチェーン攻撃を受けました。メンテナーのアカウントが侵害され、悪意あるコードを仕込んだ axios@1.14.1 と axios@0.30.4 が公開されました。npm install を実行するだけでトロイの木馬がインストールされる仕組みで、約2〜3時間の間に公開されたバージョンを取り込んだ環境が影響を受けた可能性があります。
この事件をきっかけに、筆者のメイン開発環境の npm 設定を見直しました。今回は .npmrc を使った ignore-scripts と min-release-age の設定、そして @lavamoat/allow-scripts を組み合わせた対策手順をまとめます。
攻撃の仕組み
今回の攻撃は postinstall フックを悪用したものです。問題のバージョンには悪意あるパッケージ plain-crypto-js が依存関係として追加されており、npm install を実行するだけで postinstall に登録されたスクリプトが自動実行されます。
// plain-crypto-js の package.json(抜粋)
{
"scripts": {
"postinstall": "node setup.js"
}
}
.npmrc による対策
ignore-scripts の設定
.npmrc に以下を追加することで、npm install 時に postinstall などのライフサイクルスクリプトが実行されなくなります。
# .npmrc
ignore-scripts=true
これにより今回のような postinstall を悪用した攻撃を防ぐことができます。
min-release-age の設定
min-release-age はパッケージの公開から一定期間が経過していないバージョンをインストール対象から除外する設定です。公開直後の悪意あるバージョンを自動的に取り込まないようにするための「クールダウン」機能です。
# .npmrc
ignore-scripts=true
min-release-age=7d
注意:
min-release-ageは npm 11.10.0 以降 でサポートされた機能です。node --versionやnpm --versionで使用中のバージョンを確認し、古い場合はアップグレードが必要です。
allow-scripts による例外設定
ignore-scripts=true を設定すると、bcrypt や esbuildなどのネイティブモジュールのビルドに postinstall を使うパッケージが動作しなくなります。そのような場合は @lavamoat/allow-scripts を使って信頼できるパッケージのスクリプトだけを個別に許可できます。
セットアップ手順
まず開発依存としてインストールします。
npm i -D @lavamoat/allow-scripts
production 環境で必要な場合は
-Dを外してインストールしてください。
次に以下のコマンドを実行して .npmrc への設定追加と package.json へのポリシー自動生成を行います。
# .npmrc に ignore-scripts=true を追加し、ポリシーの雛形を生成する
npx --no-install allow-scripts setup
npx --no-install allow-scripts auto
allow-scripts auto を実行すると、package.json にライフサイクルスクリプトを持つパッケージが列挙されます。許可するパッケージを true、不要なものを false に設定します。
// package.json(抜粋)
{
"lavamoat": {
"allowScripts": {
"bcrypt": true,
"esbuild": true,
"sharp": false
}
}
}
ポリシーを設定したあとは npm install の代わりに以下のコマンドで依存関係のインストールと許可スクリプトの実行を行います。
# インストール後に許可リストのスクリプトだけを実行する
npm install && npx --no-install allow-scripts run
package.json の scripts に登録しておくと運用しやすくなります。
// package.json(抜粋)
{
"scripts": {
"setup": "allow-scripts run"
}
}
Docker 環境での対応
Docker を使った開発環境では、Dockerfile 内の npm install にも同じ設定を適用する必要があります。
設定前の Dockerfile
FROM node:22-slim
WORKDIR /app
COPY package*.json ./
# postinstall スクリプトが無制限に実行される
RUN npm ci
COPY . .
設定後の Dockerfile
FROM node:22-slim
WORKDIR /app
COPY package*.json ./
# .npmrc をコピーして ignore-scripts と min-release-age を有効化する
COPY .npmrc ./
# ignore-scripts によって postinstall の自動実行を防止できる
RUN npm ci
# allow-scripts で許可したスクリプトだけを実行する
RUN npm run setup
COPY . .
.npmrc はプロジェクトルートに置いて COPY .npmrc ./ でコンテナ内に取り込みます。これにより CI/CD 環境を含むすべての Docker ビルドで同じポリシーが適用されます。
グローバル npm 設定への追加
プロジェクト単位の .npmrc に加えて、ホストマシンのグローバル設定 ~/.npmrc にも同様の設定を追加しておくことを推奨します。プロジェクトを問わず npm install を実行するすべての場面で保護が機能するようになります。
# グローバル設定に追記する
npm config set --location=global ignore-scripts true
npm config set --location=global min-release-age 7d
または ~/.npmrc を直接編集します。
# ~/.npmrc
ignore-scripts=true
min-release-age=7d
まとめ
今回の axios サプライチェーン攻撃を踏まえて、.npmrc の ignore-scripts と min-release-age、そして @lavamoat/allow-scripts を組み合わせた対策手順をまとめました。Docker 環境では .npmrc をコンテナに取り込むことで CI/CD を含めた一貫した設定が実現できます。ぜひこの機会に開発環境の npm 設定を見直してみてください。


コメント