TL;DR
- Node.js の security release は「事前告知 → 48〜72時間で LTS と Current を同時公開」のリズムで動く。告知後に動き始めると間に合わない。
- 勝負は告知前。動作中バージョンの棚卸し、依存パッケージの
overrides戦略、CI のauditfail-on-high、ロールバック手順の ADR 化までを「告知前10項目」として先に通す。 - 告知後の48時間は「トリアージ → パッチ取得 → ステージング → カナリア → 本番 → 共有」の5項目だけに絞る。
- 先にチェックリストだけ見たい人は「チェックリスト一覧(コピペ可)」へ。
はじめに
こんにちは、みねです。
Node.js を本番運用していると、半年に1〜2回、忘れた頃に security release のアナウンスが来ます。HackerOne 経由で triage されたアドバイザリが事前告知され、おおむね48〜72時間後に LTS と Current の両系統で同時にパッチがリリースされる。慣れていないチームは、告知が来てから慌てて package.json を開き、依存ツリーの棚卸しを始め、ステージング環境のメンテ枠を確保しに走る。たいてい間に合いません。
この記事のゴール:
Node.js の security release を、告知前10項目/告知後48時間5項目のチェックリストで事故らせずに回す運用を提示すること。
この記事がカバーしないこと:
- 個別 CVE の詳細解説(賞味期限が短いため、別記事や一次アドバイザリへ)
- Snyk / Socket / Sonatype 等の SCA ツール比較(別記事に切り出し予定)
- Node.js 内部の C++ / V8 実装解説
AI コーディング側のガードレール(権限・流出検知・hooks など)はAIコーディングのセキュリティ設計で4層モデルとして整理しました。本記事はその L1〜L2 を「ランタイム側」から補強する位置付けです。
なぜ「告知後対応」では遅いのか
検索結果を眺めると、多くの記事が「告知が出たあと、どう更新するか」に紙幅を割いています。ところが現場の事故は、告知後の手順ではなく告知前の準備不足で起きる。理由は単純で、Node.js の security release は事前告知から本番反映までの猶予が短いからです。
Node.js Release Schedule から逆算する
Node.js の Release Working Group は、毎年の LTS 系統と Current 系統の年次計画を公開しています。偶数バージョンは LTS、奇数バージョンは Current。LTS は Active LTS(約12ヶ月)→ Maintenance LTS(さらに約18ヶ月)と段階的に役割を変え、合計で 30ヶ月程度サポートされる。EoL(End-of-Life)を過ぎると security release は配布されません。
ここで重要なのは、自社で動いている Node.js が今どのフェーズかを即答できる体制です。Active LTS なら通常運用、Maintenance LTS なら計画的な lift-and-shift、EoL なら最優先の移行案件。フェーズが分かれば、告知が来たときに「自分たちが影響範囲か」を3分で判定できます。
HackerOne triage から公開までの典型シナリオ
Node.js の脆弱性報告は HackerOne の Node.js プログラム経由で受け付けられ、Security Working Group が triage します。Critical / High と判定されたものは、修正パッチを開発しつつ、影響範囲の絞り込みと事前告知文の準備が並行して進む。事前告知は通常、一般公開の数日前に nodejs.org のブログとメーリングリストで予告されます。
そこから48〜72時間で、対象となる LTS / Current 全系統に対する patch release が同時に公開される。この「同時公開」がポイントで、運用チームは LTS と Current を切り分けてバラバラに更新するのではなく、影響範囲を一括で見極める必要があります。
事前準備が間に合わないと起きる事故パターン3つ
実際にチームを見ていて遭遇する事故は、ほぼこの3パターンに収束します。
- 依存ツリーの把握漏れ: 直接依存だけ見て安心していたが、間接依存に脆弱なバージョンが残り、
npm auditで初めて気付く。overridesを当てる前にステージングが終わらない。 - OpenSSL バンドル更新による TLS 互換性事故: Node.js の minor up に伴い OpenSSL がバンドル更新され、外部 API の TLS 設定(旧 cipher / レガシー再ネゴシエーション)と相性が出て、本番で接続が切れる。
- EoL 系統の放置: 移行が終わっていない EoL 系統に security release が配布されず、対応不可能と判明してから初めて経営判断を仰ぐ。
3つとも告知後では取り返しがつきません。次章から、告知前にやる10項目で潰します。
LTS と Current、どちらを優先するか
告知前10項目に入る前に、前提となる判断軸を固めます。
判断フロー: 本番は LTS / 開発は Current の原則
原則はシンプルで、本番は LTS(偶数)、開発・新規機能検証は Current(奇数) です。LTS はバグフィックスと security release のみが backport されるため、機能追加による破壊変更が入りにくい。Current は新機能の検証用で、半年で次の LTS に昇格する流れです。
判断フローはこの順番で見ます。
- 本番ランタイムは Active LTS に揃っているか。
- 揃っていない場合、Maintenance LTS か Current か EoL のどれか。
- EoL なら最短で Active LTS への移行計画を立てる(security release の対象外)。
- Maintenance LTS なら次の Active LTS への計画的乗り換え時期を決める。
- Current 本番運用は原則避け、必要なら撤退条件をセットで決める。
EoL バージョンを使い続ける場合のリスク許容
EoL の Node.js を使い続けるのは、ビジネス都合で「すぐは動かせない」状況では起こり得ます。ただし、その場合はsecurity release が配布されない事実を経営判断として明示する必要があります。SLA、契約、保険条項、監査対応との関係を ADR に書き残し、移行 deadline を期日付きで握る。「動いているから」で延ばすと、いざ Critical が出たときに身動きが取れません。
マイグレーション ADR に書くべき項目
LTS 乗り換えや EoL 撤退の ADR には、最低この5項目を入れます。
- 現状の Node.js バージョンとフェーズ(Active LTS / Maintenance LTS / EoL)
- 移行先バージョンと選定理由
- 影響範囲(直接依存・間接依存・OpenSSL バンドル・ネイティブモジュール)
- 撤退条件(移行が間に合わない場合の代替策)
- 期日と責任者
よくある質問(PAA 反映)
Node.js のセキュリティリリースはいつ告知されるのか
事前告知は一般公開の数日前に nodejs.org のブログと nodejs-sec メーリングリストで予告されます。重大度は Critical / High / Medium / Low に区分され、Critical / High の場合は事前告知が出る運用です。Low は通常リリースに混ぜ込まれることもあります。
依存パッケージの脆弱性をどう棚卸しするか
pnpm audit(または npm audit)を CI で fail-on-high にして、PR 単位で検知するのが基本線です。直接依存と間接依存を分けて見るために pnpm why <package> で依存パスを確認し、間接依存のうち修正版が上流から提供されないものは package.json の pnpm.overrides / npm.overrides で固定する。SBOM(CycloneDX 形式など)を生成しておくと、棚卸しが台帳ベースで回せます。
End-of-life の Node.js を使い続けるリスクは
EoL 系統には security release が配布されません。Critical が出ても公式パッチが届かない状態になります。これは技術的問題ではなく経営判断の領域で、SLA / 契約 / 監査での説明責任が発生します。短期的に運用継続するなら、外部ネットワーク露出の最小化(リバースプロキシ前段で WAF、内部のみ)、依存パッケージ側でのパッチ供給、移行期日のコミットをセットにします。
セキュリティリリース告知から本番反映までの目安時間は
Critical / High 想定では「告知後24時間以内にステージング、48時間以内にカナリア、72時間以内に本番反映」を目標にします。これは Node.js Security Release Process の同時公開タイムラインから逆算した運用基準で、達成には告知前10項目の準備が前提です。
告知前にやる10項目(事前棚卸し編)
ここからが本記事の主軸です。10項目を1週間以内に1度通すと、次回告知時の事故率が大きく下がります。
① 動作中の Node.js バージョンを SBOM で棚卸し
本番・ステージング・開発で動いている Node.js のバージョンを SBOM 化します。pnpm sbom や cyclonedx-npm で CycloneDX 形式のファイルを出力し、リポジトリにコミットしておく。複数サービスを抱えている場合、サービスごとの台帳ではなく組織横断の一覧表にまとめると、告知時のトリアージが3分で終わります。
# CycloneDX 形式で SBOM を生成(pnpm の場合)
pnpm dlx @cyclonedx/cyclonedx-npm --output-format JSON --output-file sbom.json
② LTS / Current / EoL のマッピング表を作る
サービスごとの Node.js バージョンを、Active LTS / Maintenance LTS / Current / EoL でマッピングします。EoL 行が1つでもあれば最優先で次章の移行 ADR に進む。Maintenance LTS は1年以内の Active LTS 乗り換え計画を立てる。Current 本番は撤退条件をセットで明文化します。
| サービス | Node.js バージョン | フェーズ | 推奨アクション |
|---|---|---|---|
| api-main | 22.x | Active LTS | 通常運用 |
| api-legacy | 18.x | Maintenance LTS | Q3 までに 22.x へ移行 |
| batch-old | 16.x | EoL | 最優先移行(security release 対象外) |
③ 直接依存パッケージの semver 上限を見直す
package.json の dependencies を見直し、メジャーバージョンを ^ で広く取りすぎていないか確認します。security release で不本意な major up が連動するのを防ぐため、特にネイティブモジュール(bcrypt、sharp、better-sqlite3 等)は ~ 以下に絞る運用を検討。Renovate / Dependabot の自動 PR と組み合わせれば、計画的な major up が回ります。
④ 間接依存の overrides 戦略を決める
間接依存(transitive dependencies)のうち、上流から修正版が提供されないものに対して overrides を当てる方針を決めます。pnpm なら package.json の pnpm.overrides、npm なら overrides フィールド。ピン留めの期限(次のメジャーリリースで外す等)を ADR に書き、放置しないようにします。
{
"pnpm": {
"overrides": {
"lodash@<4.17.21": "4.17.21",
"minimist@<1.2.6": "1.2.6"
}
}
}
⑤ Dependabot / Renovate の自動 PR 設定を確認
CI で自動 PR が滞留していないか確認します。Renovate の groupName で Node.js minor / patch 系を1つの PR にまとめ、schedule で深夜帯に走らせる。バラバラに来る PR は運用負荷で破綻します。
// renovate.json
{
"extends": ["config:base"],
"packageRules": [
{
"matchPackageNames": ["node"],
"groupName": "node-minor-patch",
"schedule": ["after 11pm and before 5am every weekday"]
}
]
}
⑥ CI で pnpm audit --production を fail-on-high にする
pnpm audit --production を CI に組み込み、High 以上で fail させる設定にします。GitHub Actions の例:
- name: Audit production dependencies
run: pnpm audit --prod --audit-level=high
npm audit の偽陽性が増えてきたチームは、追加で SCA ツール(GitHub Advanced Security の Dependabot Alerts、Renovate の vulnerabilityAlerts 等)を併用して二重化する。これはsecret scanning と同じく CI で fail させる思想で、検知ラインを一本化するのが要点です。
⑦ ステージング環境で Node.js minor up の動作確認スクリプトを用意
「Node.js のバージョンを上げるだけで一通り回るか」を確認するスモークテストを用意します。pnpm test、pnpm build、主要エンドポイントの health check、外部 API への TLS 接続テスト。security release が来たときに「いつものスクリプトを叩く」だけにしておけば、判断のレイテンシが消えます。
⑧ OpenSSL バンドル更新時の TLS 影響を事前テスト
Node.js は OpenSSL を内部にバンドルしており、minor up に伴い OpenSSL も更新されることがあります。過去には Node.js v17 → v18 で TLS 関連の挙動変更があり、レガシーな再ネゴシエーション設定の API と接続不能になる事故が起きています。
事前テストとしては、外部 API への TLS ハンドシェイクを最小スクリプトで確認しておく。
// tls-smoke.js: 主要外部APIへのTLS接続を確認
import { request } from "node:https";
const targets = ["https://api.example.com/health", "https://oauth.partner.com"];
for (const url of targets) {
await new Promise((resolve, reject) => {
const req = request(url, (res) => {
console.log(url, res.statusCode);
resolve();
});
req.on("error", reject);
req.end();
});
}
レガシー暗号や --openssl-legacy-provider フラグに依存しているプロジェクトは、移行時期を ADR で握っておきます。
⑨ ロールバック手順を ADR 化しておく
更新が失敗したときに「何分以内に」「どのバージョンへ」「誰の判断で」戻すかを ADR に書きます。
Claude Code hooks の責務分担と同じ考え方で CI に置く、つまり「判断は人間、実行は自動化」の境界を明示する。具体的には、コンテナイメージのタグ戻し、Helm chart の --rollback、Lambda のエイリアス切り戻しなど、サービス特性に合わせた最短手順を書き残します。
⑩ セキュリティアドバイザリの通知チャンネルを Slack に流す
nodejs-sec メーリングリスト、GitHub の Security Advisories、HackerOne の Disclosure を Slack に流すチャンネルを作ります。RSS → Slack の Incoming Webhook で十分です。告知に気付くまで が最大のレイテンシなので、ここは自動化必須。チャンネルは SRE / EM / バックエンドリードを @here 対象に含めます。
告知後48時間でやる5項目(即応編)
告知前10項目が通っていれば、告知後はこの5項目だけに集中できます。
① 告知内容のトリアージ(影響有無の即時判定)
事前告知の本文を読み、対象バージョン・重大度・攻撃ベクトルを SBOM と突き合わせます。自社の動作中バージョンが対象範囲外なら、ここで終わり。対象範囲内なら次へ進みます。トリアージは30分以内に完了させる目安です。
② パッチ済みバージョンの取得と CI 実行
公開された patch release のバージョンを Dockerfile / engines / CI ランナーで指定し、PR を作成します。Renovate の自動 PR が先に来ていれば、それをベースに事実確認だけする。CI でテスト・audit・smoke が通ることを確認します。
③ ステージング → カナリア → 本番のロールアウト
PR をマージしたら、ステージングへデプロイ、TLS smoke を含む動作確認、カナリアで5〜10%トラフィックに流して30分〜1時間観察、問題なければ本番100%へ。各段階で観測指標(エラーレート、レイテンシ、TLS ハンドシェイク失敗率)を見ます。
④ 失敗時のロールバック判断基準
ロールバック ADR の判断基準を引き、「○分以内にエラーレートが○%を超えたら戻す」を機械的に判断します。判断者を1人に決めておかないと、議論で時間が溶ける。SRE / EM のどちらが On-call かを事前に決めておきます。
⑤ 事後ログとアドバイザリ反映の社内共有
告知から本番反映までのタイムライン、ロールバック有無、影響範囲、次回への学びを共有用のテンプレで残します。これが次回告知時の判断材料になり、告知前10項目を更新する根拠になる。社内 Wiki / ADR / Slack canvas に1ページ作って終わりにします。
チェックリスト一覧(コピペ可)
告知前10項目チェックリスト
- [ ] ① 動作中の Node.js バージョンを SBOM で棚卸し
- [ ] ② LTS / Current / EoL のマッピング表を作る
- [ ] ③ 直接依存パッケージの semver 上限を見直す
- [ ] ④ 間接依存の overrides 戦略を決める
- [ ] ⑤ Dependabot / Renovate の自動 PR 設定を確認
- [ ] ⑥ CI で pnpm audit --production を fail-on-high にする
- [ ] ⑦ ステージング環境で Node.js minor up の動作確認スクリプトを用意
- [ ] ⑧ OpenSSL バンドル更新時の TLS 影響を事前テスト
- [ ] ⑨ ロールバック手順を ADR 化しておく
- [ ] ⑩ セキュリティアドバイザリの通知チャンネルを Slack に流す
告知後48時間5項目チェックリスト
- [ ] ① 告知内容のトリアージ(影響有無の即時判定)
- [ ] ② パッチ済みバージョンの取得と CI 実行
- [ ] ③ ステージング → カナリア → 本番のロールアウト
- [ ] ④ 失敗時のロールバック判断基準
- [ ] ⑤ 事後ログとアドバイザリ反映の社内共有
関連 ADR テンプレート
# ADR: Node.js セキュリティリリース対応方針
## Status
Accepted
## Context
Node.js security release は告知から48〜72時間で同時公開される。
## Decision
- 本番は Active LTS、開発は Current
- EoL 系統は最優先で Active LTS に移行
- 間接依存は overrides で固定し、ピン留め期限を ADR に書く
- ロールバック判断者は SRE On-call
## Consequences
- 告知後48時間以内にカナリア反映が可能
- 自動 PR 滞留を Renovate group で吸収
一次情報: 自社運用での実測タイムライン
参考までに、直近の Node.js security release 対応で自チームが計測したタイムラインを共有します。
| 段階 | 経過時間(告知起点) | 内容 |
|---|---|---|
| 告知検知 | 0:05 | nodejs-sec → Slack 通知でトリガ |
| トリアージ完了 | 0:30 | SBOM 突合、影響範囲確定 |
| Renovate PR 作成 | 1:00 | 自動 PR がベースバージョンを上げる |
| CI 通過 | 2:30 | audit / test / smoke すべて green |
| ステージング反映 | 4:00 | TLS smoke 含む動作確認完了 |
| カナリア5% | 8:00 | 観測30分問題なし |
| 本番100% | 12:00 | エラーレート横ばい |
告知前10項目が事前に通っていたため、12時間で本番100%まで到達できました。逆に、項目⑦⑧が抜けていた頃は、ステージングで TLS 不具合に当たり24時間以上溶けていました。
まとめと次のアクション
Node.js の security release 対応は、告知後の手順論ではなく告知前の棚卸しで決まる。本記事の告知前10項目を、まずは自社リポジトリで1週間以内に1度通してください。1度通しておけば、次回告知時に動けます。
関連トピックとして、AI コーディング側のセキュリティ全体像はAIコーディングのセキュリティ設計で4層モデルとして整理しています。CI 段の検知思想はGitHub MCP の secret scanning 運用、ロールバック判断と自動化の境界はClaude Code hooks の責務分担が踏み込んだ整理です。
Node.js の更新運用を組織横断で設計したい場合は、お気軽にお問い合わせからご相談ください。
参考リンク
- Node.js Release Schedule (nodejs/release)
- Node.js Security Release Process
- Node.js HackerOne Program
- pnpm audit ドキュメント
- GitHub Dependabot ドキュメント
- CycloneDX SBOM 仕様
last_reviewed: 2026-05-01 ── LTS スケジュール / Release Process の数値は半年ごとに見直す。
関連記事
- Bun 1.3を本番採用すべきか — Node.js LTS と Bun のハイブリッド運用を ADR に落とすための4軸判断テンプレ。Node.js LTS の安定性と Bun の開発体験を併用する「両方使う」現実解
