Node.js の環境を DevContainer に封じ込めよう
この記事は mstdn.maud.io Advent Calendar 2025 10日目の記事です.
11月24日 postman や zapier など 500 以上のパッケージがサプライチェーン攻撃を受けていたことが報告されました.
Shai Hulud Strikes Again (v2) - Socket
postmanやzapierが攻撃されていた。bunをインストールして悪意のあるスクリプトが動くっぽい / Shai Hulud Strikes Again (v2) - Socket https://t.co/q0xsBHYyhh
— hiroppy (@about_hiroppy) November 24, 2025
この Shai Hulud というサプライチェーン攻撃は実は9月にも同様に発生しており, @ctrl/tinycolor パッケージなども同様の手口によって攻撃を受けました.
みなさん驚きなんと今年2回目!w
なんとかならんのか?
Node.js のエコシステムは非常に大きいもので,全世界に数百万のパッケージが存在している上に,それらのパッケージは全世界のプロダクトに利用されています.
私個人としては Node.js のエコシステムに関しては 呆れ と 諦念 の感情が強く,この脆弱なシステムはもはやどうしようもないと思っています.
(というかどうにかなってたら恐らく Deno は産まれてないし1,こんなサプライチェーン攻撃が頻繁には行われないでしょう)
DevContainer のすゝめ
エコシステムが脆弱なら,ローカルを最後の砦として守るしかありません.
私が最近使っているのは DevContainer です.つい最近も PHP をローカルから追い出して気持ちよくなってました2.
DevContainer に求められること
1. Node.js のバージョン管理ができる
Node.js のバージョン管理には mise や asdf などの外部ツールを使うのが一般的ですが,DevContainer の場合は,それらは単一の Docker Image なのでバージョン管理が簡単です. (Renovate にも更新をさせることができる)
2. 全ての開発環境を Docker Container 内で完結できる
DevContainer は起動した Docker Container に VSCode で接続する仕組みなので, DB などそれ以外の環境を DevContainer に含めれれば,ローカルに何もインストールせずに開発が完結します.
3. ローカルに影響を与えない
何と言ってもこれ.
基本ローカルはクリーンにしておきたいので,DevContainer 内に全ての開発環境を閉じ込めれば,ローカルに影響を与えずに済みます.
最小構成で DevContainer を作ってみる
DevContainer を作るにはプロジェクトルートに .devcontainer ディレクトリを作成し,その中に devcontainer.json を作成します.これが DevContainer の設定ファイルになります.
DevContainer に接続する VSCode は Standalone 3 となるので,customizations フィールドで接続先の VSCode で使いたい拡張機能をインストールしたり,設定を追加したりできます.つまり開発環境を他のメンバーと共有でき,なおかつ完全分離ができるわけです.
次に Dockerfile を作成します.この Dockerfile で作成する Docker Image を実際にコンテナ内で使うことになります.
FROM node:24.11.1
# 必要なら追加のツールをここでインストールすることもできる
# RUN apt-get update && apt-get install -y ...
これで Node.js v24.11.1 を使う DevContainer の完成です. 起動するには VSCode のコマンドパレットから "Dev Containers: Reopen in Container" を実行します.

すると Docker Image のビルド, DevContainer のインストールが行われ,VSCode がコンテナに接続します.

試しに以下のような静的テキストを返す簡易 HTTP サーバーを作成してみます.
;
;
PORT,;
ポートは自動的に Forward されるので,コンテナ内でサーバーを起動すれば,ローカルホストからアクセスできます.


node_modules も DevContainer に閉じ込めよう
Node.js のプロジェクトでは node_modules ディレクトリが大量に生成され,ローカルにインストールされると非常に邪魔です.(サプライチェーン攻撃にも利用される)
デフォルトの DevContainer の挙動では,ホストのプロジェクトディレクトリがコンテナ内にマウントされるため,node_modules もホストに作成されてしまいます.

これを防ぐ方法として Docker の Volue Trick を利用して,node_modules をコンテナ内に閉じ込める方法があります.
"mounts":
DevContainer は魔法の杖ではない
ここまで散々 DevContainer のことを持ち上げましたが,DevContainer でもサプライチェーン攻撃を完全に防げるわけではありません. 侵害された npm パッケージをインストールすれば,コンテナ内では攻撃を受けます.
ただ DevContainer は Docker Container の中に開発環境を構築するので,万が一攻撃を受けたとしてもそのコンテナを破棄すればローカルには影響を与えません.
--ignore-scripts オプションを使う
npm や yarn, pnpm にはインストール時に --ignore-scripts オプションを付与することで,パッケージのインストール時に実行されるスクリプトを無効化できます.
Shai Hulud のような攻撃はインストール時にスクリプトを実行することで行われるため,このオプションを付与することで攻撃を防げる可能性があります.
Deno の v2.0 リリース時に公式から公開された PV "Programming Should Be Simple" は npm の脆弱さをいじってるシーンがある.
PHP は別に業務でも書いてないしなんなら嫌いな言語の1つだが,大学の講義で仕方なく使わざる終えなかったので DevContainer に封じ込めた.
Remote Connection のような挙動をするので,ローカルの VSCode とは別に拡張機能や設定を持てる.