依存関係脆弱性管理とSBOM CycloneDX完全ガイド|npm audit・OSV・Dependabot・サプライチェーンセキュリティ2026
- 依存関係脆弱性管理の2026年定石は lockfile 固定 → CycloneDX SBOM 生成 → npm audit + OSV の二重スキャン → Dependabot 更新 → Critical CVE triage の5段。
- SBOM CycloneDX は監査・インシデント対応の「部品表」、npm audit / OSV は日次の検知、GitHub Dependabot は修正 PR の自動化を担う。
- アプリ層の セキュリティヘッダー と CSP で多層防御を重ね、修正版がない CVE は VEX で影響評価を明示する——これがサプライチェーンセキュリティの実務的最小構成だ。
なぜ依存関係脆弱性管理が「2026年の必須インフラ」なのか
現代の Web アプリケーションは、自前コードより npm 依存パッケージの方が行数・攻撃面積ともに大きい ことがほとんどだ。React、Next.js、Astro、Express——いずれも数千の transitive dependency を引き連れる。1つだけに既知 CVE(Common Vulnerabilities and Exposures)があれば、認証 bypass、プロトタイプ汚染、リモートコード実行(RCE)につながる。
2024〜2026年にかけて、サプライチェーン攻撃は typosquatting(lodash → l0dash)、maintainer アカウント乗っ取り、ビルドパイプラインへの malware 注入(Shai-Hulud、XZ Utils 事件の教訓)へと進化した。依存関係を「npm install したら終わり」で放置することは、消防設備の点検をしないビルと同じリスクだ。
| 対策なし | SBOM + スキャン + Dependabot |
|---|---|
| どのバージョンが本番か不明 | CycloneDX SBOM で全コンポーネントを列挙 |
| CVE 公開後に数日〜数週間放置 | Dependabot が PR を自動作成、SLA で triage |
| 監査で「部品表ください」に即答不能 | リリース artifact に SBOM JSON を添付 |
| 修正版なし CVE の説明責任が曖昧 | VEX で not_affected / mitigated を文書化 |
| アプリ層防御のみ | CSP・ヘッダーと組み合わせた多層防御 |
本記事では SBOM CycloneDX を中心に、npm audit、OSV(Open Source Vulnerabilities)、GitHub Dependabot を組み合わせた実務パイプラインを、コピペ可能な YAML / CLI 例付きで解説する。最後に セキュリティヘッダー一覧 と CSP 設定ガイド への接続——依存パッケージの穴をアプリ層でどう補うか——も触れる。
package-lock.json をコミットし、npm ci を CI の唯一のインストール手段に固定する
@cyclonedx/cyclonedx-npm を devDependency に追加し、npm run sbom で CycloneDX JSON を生成する
npm audit --audit-level=high と OSV Scanner を GitHub Actions で pull_request 時に実行する
.github/dependabot.yml で npm と GitHub Actions の週次更新を有効化する
Critical/High CVE は Dependency-Track または GitHub Security タブで triage し、SLA を設定する
リリース時に SBOM を artifacts として保存し、Sigstore cosign で署名する(任意)
修正不能な CVE は VEX を発行し、CSP・セキュリティヘッダーで多層防御を補完する
SBOM(Software Bill of Materials)の基礎
SBOM はソフトウェアを構成する 部品のリスト だ。ハードウェアの BOM(部品表)と同様、名称・バージョン・供給元・ライセンス・ハッシュを機械可読形式で記述する。セキュリティインシデント時に「Log4j 2.x を含むか?」「影響を受ける @babel/traverse のバージョンは?」を 数秒で回答 できるのが最大の価値だ。
CycloneDX 1.6 の位置づけ
2026年時点で npm エコシステムでは CycloneDX 1.6 が de facto 標準に近い。OWASP Dependency-Track、Anchore Grype、Trivy、GitHub Dependency Graph など主要ツールが CycloneDX JSON / XML を入出力できる。
| 形式 | 特徴 | npm プロジェクトでの用途 |
|---|---|---|
| CycloneDX 1.6 | VEX、コンポーネント hash、依存グラフ | CI 生成・Dependency-Track 連携 |
| SPDX 2.3 / 3.0 | ライセンスコンプライアンスに強い | 法務・OSS 監査向け |
| Syft SBOM | コンテナイメージ向け | Docker レイヤ + npm の複合 |
CycloneDX の components 配列には、各 npm パッケージが type: library、purl(Package URL)、hashes(integrity)付きで列挙される。dependencies セクションで依存グラフも表現できる。
pkg:npm/[email protected] のような標準識別子。OSV Database や Dependency-Track は purl で脆弱性を突合する。SBOM に purl が無いと、スキャナがコンポーネントを正しくマッチできない。
npm audit:lockfile ベースの第一防衛線
npm audit は npm CLI 組み込みの脆弱性スキャナだ。package-lock.json に記録された 実際に解決されたバージョン を対象に、GitHub Advisory Database 等と照合する。
基本コマンドと出力の読み方
# ローカルで High 以上のみ表示
npm audit --audit-level=high
# JSON 形式(CI 向け)
npm audit --json > reports/npm-audit.json
# 自動修正(破壊的変更あり得る — CI では非推奨)
npm audit fix
# semver 範囲内のみ修正(比較的安全)
npm audit fix --force=false
npm audit の severity は Critical / High / Moderate / Low の4段。2026年の実務 SLA 例:
| Severity | 目標修正期限 | CI ゲート |
|---|---|---|
| Critical | 72時間以内 | PR ブロック |
| High | 2週間以内 | PR ブロック(例外ラベルあり) |
| Moderate | 次のスプリント | warn のみ |
| Low | 四半期レビュー | 記録のみ |
package.json スクリプト例
{
"name": "my-web-app",
"version": "2.1.0",
"private": true,
"scripts": {
"preinstall": "npx only-allow npm",
"audit:ci": "npm audit --audit-level=high --json > reports/npm-audit.json || node scripts/check-audit.mjs",
"sbom": "cyclonedx-npm --output-file dist/sbom.cyclonedx.json --spec-version 1.6",
"sbom:validate": "cyclonedx validate --input-file dist/sbom.cyclonedx.json",
"security:all": "npm run sbom && npm run audit:ci && osv-scanner --lockfile=package-lock.json --format=json -o reports/osv.json"
},
"devDependencies": {
"@cyclonedx/cyclonedx-npm": "^2.0.0",
"@cyclonedx/cyclonedx-cli": "^0.27.0",
"osv-scanner": "^1.7.0"
},
"engines": {
"node": ">=20.0.0",
"npm": ">=10.0.0"
}
}
scripts/check-audit.mjs(CI ゲート用)
#!/usr/bin/env node
import { readFileSync } from 'node:fs';
const ALLOWED_CRITICAL = Number(process.env.AUDIT_ALLOW_CRITICAL ?? 0);
const ALLOWED_HIGH = Number(process.env.AUDIT_ALLOW_HIGH ?? 0);
const reportPath = process.argv[2] ?? 'reports/npm-audit.json';
let report;
try {
report = JSON.parse(readFileSync(reportPath, 'utf8'));
} catch {
console.error('[audit] Report not found. Run npm audit --json first.');
process.exit(1);
}
const meta = report.metadata?.vulnerabilities ?? {};
const critical = meta.critical ?? 0;
const high = meta.high ?? 0;
const moderate = meta.moderate ?? 0;
const low = meta.low ?? 0;
console.log(`[audit] critical=${critical} high=${high} moderate=${moderate} low=${low}`);
if (critical > ALLOWED_CRITICAL) {
console.error(`[audit] FAIL: ${critical} critical (allowed: ${ALLOWED_CRITICAL})`);
process.exit(1);
}
if (high > ALLOWED_HIGH) {
console.error(`[audit] FAIL: ${high} high (allowed: ${ALLOWED_HIGH})`);
process.exit(1);
}
console.log('[audit] PASS');
process.exit(0);
npm audit fix は lockfile を書き換え、semver 範囲外へバンプする --force 相当の挙動を含み得る。CI では 検知のみ を行い、修正は Dependabot PR または人間が review して merge する。
OSV Database と OSV Scanner:エコシステム横断の第二防衛線
OSV(Open Source Vulnerabilities) は Google が運営する、複数エコシステムを横断する脆弱性データベースだ。npm だけでなく PyPI、Go、Crates.io、RubyGems 等を 統一スキーマ で扱える。モノレポ(Node + Python ツール)や、npm advisory に未登録の CVE を拾う セーフティネット になる。
OSV Scanner のインストールと実行
# GitHub Releases からバイナリ取得(Linux/macOS/Windows)
curl -LO https://github.com/google/osv-scanner/releases/download/v1.7.0/osv-scanner_1.7.0_linux_amd64
chmod +x osv-scanner_1.7.0_linux_amd64
sudo mv osv-scanner_1.7.0_linux_amd64 /usr/local/bin/osv-scanner
# lockfile スキャン
osv-scanner --lockfile=package-lock.json
# SBOM 入力(CycloneDX)
osv-scanner --sbom=dist/sbom.cyclonedx.json --format=json -o reports/osv-from-sbom.json
# 特定 CVE を除外(修正不能・影響なしの記録)
osv-scanner --lockfile=package-lock.json --ignore-vulns=GHSA-xxxx-yyyy-zzzz
npm audit と OSV の使い分け
| npm audit | OSV Scanner |
|---|---|
| npm エコシステムに最適化 | 複数エコシステム横断 |
| npm CLI 標準搭載 | 別バイナリ / GitHub Action |
| advisory の fixAvailable 情報 | OSV レコードへの deep link |
| PR ごとの高速ゲート向き | nightly 全量 + SBOM 突合向き |
| GitHub Advisory と連携 | GitHub + PyPI + 独自ソース統合 |
両方走らせて 差分がある CVE を triage するのが2026年のベストプラクティスだ。npm audit で検出され OSV で検出されない(またはその逆)ケースは、advisory 登録タイミングの差が原因であることが多い。
CycloneDX SBOM の生成:@cyclonedx/cyclonedx-npm
@cyclonedx/cyclonedx-npm は package-lock.json v2/v3 から CycloneDX SBOM を生成する公式ツールだ。
生成コマンド
npm install --save-dev @cyclonedx/cyclonedx-npm@2
# CycloneDX 1.6 JSON を出力
npx cyclonedx-npm \
--output-file dist/sbom.cyclonedx.json \
--spec-version 1.6 \
--output-reproducible \
--validate
# 生成物の検証
npx cyclonedx validate --input-file dist/sbom.cyclonedx.json --input-format json
生成される CycloneDX JSON の構造(抜粋)
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
"version": 1,
"metadata": {
"timestamp": "2026-06-22T09:00:00Z",
"tools": {
"components": [
{
"type": "application",
"name": "cyclonedx-npm",
"version": "2.0.0"
}
]
},
"component": {
"type": "application",
"name": "my-web-app",
"version": "2.1.0",
"purl": "pkg:npm/[email protected]"
}
},
"components": [
{
"type": "library",
"name": "lodash",
"version": "4.17.21",
"purl": "pkg:npm/[email protected]",
"hashes": [
{
"alg": "SHA-512",
"content": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef123456"
}
],
"licenses": [
{
"license": {
"id": "MIT"
}
}
]
},
{
"type": "library",
"name": "express",
"version": "4.21.2",
"purl": "pkg:npm/[email protected]"
}
],
"dependencies": [
{
"ref": "pkg:npm/[email protected]",
"dependsOn": [
"pkg:npm/[email protected]",
"pkg:npm/[email protected]"
]
}
]
}
--output-reproducible を付けると timestamp 以外の揺れを抑え、同一 lockfile から同一 SBOM を再現できる。リリース artifact の integrity 検証に有用だ。
Dependency-Track への SBOM アップロード
OWASP Dependency-Track は SBOM を受け取り、NVD・GitHub Advisory と突合して ポリシー違反 を通知するセントラル DB だ。
# API で SBOM をアップロード
curl -X POST "https://dependency-track.example.com/api/v1/bom" \
-H "X-Api-Key: ${DTRACK_API_KEY}" \
-H "Content-Type: multipart/form-data" \
-F "project=550e8400-e29b-41d4-a716-446655440000" \
-F "bom=@dist/sbom.cyclonedx.json"
GitHub Enterprise や GitLab Ultimate を使っている場合は、組み込み Dependency Scanning で代替できる。OSS チームは Dependency-Track + CycloneDX の組み合わせがコスト効率が高い。
GitHub Dependabot:修正 PR の自動化
Dependabot は GitHub ネイティブの依存関係更新ボットだ。脆弱性 advisory が公開されると セキュリティアップデート PR を自動作成する。2026年時点では version updates(定期バージョンアップ)と security updates(CVE 対応)の2モードがある。
.github/dependabot.yml 完全例
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "Asia/Tokyo"
open-pull-requests-limit: 10
groups:
production-dependencies:
dependency-type: "production"
patterns:
- "*"
update-types:
- "minor"
- "patch"
development-dependencies:
dependency-type: "development"
patterns:
- "*"
update-types:
- "patch"
commit-message:
prefix: "deps"
include: "scope"
labels:
- "dependencies"
- "automated"
reviewers:
- "security-team"
ignore:
- dependency-name: "eslint"
versions: ["9.x"]
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
commit-message:
prefix: "ci"
labels:
- "github-actions"
Dependabot セキュリティアラートの運用
GitHub Security タブで Critical / High アラートを確認し、Dependabot PR が自動作成されているかチェック
PR の CI(npm audit、OSV、ユニットテスト、E2E)が green であることを確認
major 更新は CHANGELOG と breaking change を読み、必要なら feature ブランチで手動検証
merge 後、本番デプロイパイプラインで新 lockfile が反映されたことを確認
修正不能 CVE は VEX を発行し、Security タブで 'Dismiss' 理由を documented risk として記録
四半期ごとに ignore リストと SLA 遵守率をレビュー
auto-merge の条件例(patch のみ)
# .github/workflows/dependabot-automerge.yml
name: Dependabot auto-merge
on: pull_request
permissions:
contents: write
pull-requests: write
jobs:
automerge:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v2
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Enable auto-merge for patch/minor
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
run: gh pr merge --auto --squash "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Critical CVE の PR は auto-merge せず、セキュリティ担当の approve 必須 にするのが無難だ。
GitHub Actions:脆弱性 CI パイプライン完全例
PR ごとに SBOM 生成 → npm audit → OSV Scanner → SBOM artifact 保存 を走らせる workflow だ。
name: Dependency Security
on:
pull_request:
branches: [main]
push:
branches: [main]
schedule:
- cron: "0 18 * * 1"
permissions:
contents: read
security-events: write
jobs:
sbom-and-audit:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Generate CycloneDX SBOM
run: |
npx cyclonedx-npm \
--output-file dist/sbom.cyclonedx.json \
--spec-version 1.6 \
--output-reproducible
npx cyclonedx validate --input-file dist/sbom.cyclonedx.json
- name: npm audit (fail on high+)
run: |
npm audit --audit-level=high --json > reports/npm-audit.json || true
node scripts/check-audit.mjs reports/npm-audit.json
env:
AUDIT_ALLOW_CRITICAL: "0"
AUDIT_ALLOW_HIGH: "0"
- name: OSV Scanner
uses: google/osv-scanner-action@v1
with:
scan-args: |-
--lockfile=package-lock.json
--format=sarif
--output=reports/osv.sarif
- name: Upload SARIF to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: reports/osv.sarif
- name: Upload SBOM artifact
uses: actions/upload-artifact@v4
with:
name: sbom-cyclonedx-${{ github.sha }}
path: dist/sbom.cyclonedx.json
retention-days: 90
release-sbom:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: sbom-and-audit
runs-on: ubuntu-latest
steps:
- name: Download SBOM
uses: actions/download-artifact@v4
with:
name: sbom-cyclonedx-${{ github.sha }}
- name: Attach SBOM to GitHub Release
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/v')
with:
files: sbom.cyclonedx.json
schedule トリガーで 週次フルスキャン を走らせ、PR 以外のタイミング(advisory 深夜公開など)もカバーする。
VEX:修正版がない CVE の影響評価
VEX(Vulnerability Exploitability eXchange) は CycloneDX 1.4+ でサポートされる、SBOM への 脆弱性ステータス付記 だ。「CVE-2024-XXXX は当製品では not_affected」などを機械可読で宣言し、監査人・顧客・スキャナに伝える。
VEX ステータス一覧
| ステータス | 意味 | 例 |
|---|---|---|
not_affected | 脆弱なコードパスを使用していない | devDependency のみ |
affected | 影響あり、修正待ち | 本番 runtime で使用中 |
fixed | 修正版に更新済み | 1.2.3 → 1.2.4 |
under_investigation | 調査中 | triage 初期 |
CycloneDX VEX 拡張例
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"version": 1,
"vulnerabilities": [
{
"id": "GHSA-952p-6rrq-rcjv",
"source": {
"name": "GitHub Advisory Database",
"url": "https://github.com/advisories/GHSA-952p-6rrq-rcjv"
},
"ratings": [
{
"severity": "high",
"method": "CVSSv3",
"score": 7.5,
"vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
}
],
"analysis": {
"state": "not_affected",
"justification": "code_not_reachable",
"detail": "当該パッケージはビルド時のみ使用。本番バンドルに含まれない。"
},
"affects": [
{
"ref": "pkg:npm/@babel/[email protected]"
}
]
}
]
}
VEX を乱用すると監査信用を失う。not_affected は技術的根拠(コードパス分析、バンドル解析)を PR / チケットに残す こと。
サプライチェーンセキュリティ2026:Sigstore・SLSA・npm provenance
SBOM と脆弱性スキャンに加え、2026年のエンタープライズ要件では 成果物の出所(provenance) も問われる。
npm publish provenance
npm は GitHub Actions から publish する際、Sigstore ベースの provenance attestation を付与できる。
# .github/workflows/publish-npm.yml(抜粋)
- name: Publish to npm with provenance
run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
npmjs.com 上で Verified Publisher バッジが表示され、typosquat 対策の一助になる。社内 private registry でも同様の attestation 基盤(Harbor、Artifactory)が普及している。
SLSA レベルとの対応
| SLSA Level | 要件概要 | npm プロジェクトでの実装 |
|---|---|---|
| Build L1 | ビルドの記録 | GitHub Actions ログ |
| Build L2 | 改ざん防止 CI | branch protection + Required Check |
| Build L3 | 署名付き provenance | npm —provenance、cosign |
| Build L4 | 厳格な二段階 review | 本番 deploy 承認フロー |
完全な SLSA L3 までは求められない SMB でも、lockfile コミット + CI ゲート + SBOM 保存 は2026年の最低ラインだ。
lockfile と npm ci の固定
# 開発者ローカル
npm install [email protected]
git add package.json package-lock.json
# CI / 本番ビルド(唯一許可)
npm ci --ignore-scripts
--ignore-scripts は postinstall malware(Shai-Hulud 型攻撃)のリスクを下げる。どうしても scripts が必要なパッケージ(esbuild 等)は allowlist で管理する。
; .npmrc(CI 用)
ignore-scripts=true
audit=true
fund=false
engine-strict=true
多層防御:SBOM とアプリ層セキュリティの接続
依存パッケージの CVE は 100% 即時修正できない。修正版リリース待ち、major bump の breaking change、transitive dependency の塊——現実には「脆弱だが動かす」期間が存在する。その間の リスク低減 として、アプリケーション層の防御が効く。
CSP とセキュリティヘッダー
Content-Security-Policy 設定ガイド で述べた script-src の許可リスト は、依存ライブラリ経由の XSS やインジェクション被害を限定する。たとえば prototype pollution で DOM に script が注入されても、CSP が inline / 未知ドメインを拒否すれば実行を止められる場合がある。
セキュリティヘッダー一覧と設定 の HSTS、X-Content-Type-Options、Referrer-Policy も、依存パッケージ由来の情報漏洩経路を狭める。SBOM triage で「修正版なし High CVE」が出たとき、VEX + CSP 強化 + 機能フラグ無効化 をセットでチケット化するのが2026年の runbook 例だ。
# 依存パッケージ CVE 暫定対応時の CSP 強化例(nginx)
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none';" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
CSP やヘッダーは 被害の限定(containment) であり、脆弱パッケージの 根治(remediation) ではない。SBOM + Dependabot で根治を目指しつつ、暫定期間は多層防御でリスクを下げる——両輪で設計する。
インシデント対応 Runbook:CVE 公開から修正まで
GitHub Security / npm audit / OSV / Dependency-Track から Critical アラートを検知
CycloneDX SBOM で affected component の purl と依存経路(dependsOn)を特定
Dependabot PR または手動 bump で修正版へ更新。lockfile 差分を PR で review
修正版が無い場合: VEX 草案作成、機能影響調査、CSP/ヘッダー暫定強化を parallel 実行
merge 後、新 SBOM を artifact として保存し、顧客・社内ステークホルダーへ通知
postmortem で SLA 遵守、検知遅延、auto-merge 可否を振り返る
通知テンプレート(Slack)
// scripts/notify-cve.mjs
const webhookUrl = process.env.SLACK_SECURITY_WEBHOOK;
const cve = process.env.CVE_ID ?? 'GHSA-unknown';
const packageName = process.env.PKG_NAME ?? 'unknown';
const fixedVersion = process.env.FIXED_VERSION ?? 'none';
const text = fixedVersion === 'none'
? `:warning: *${cve}* affects \`${packageName}\`. No fix available. VEX + mitigation in progress. SBOM updated.`
: `:white_check_mark: *${cve}* fixed in \`${packageName}@${fixedVersion}\`. Dependabot PR ready for review.`;
await fetch(webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text }),
});
モノレポ・pnpm・yarn への拡張
本記事は npm + package-lock.json を前提にしたが、概念は他パッケージマネージャにも移植できる。
| マネージャ | lockfile | SBOM ツール | audit 相当 |
|---|---|---|---|
| npm | package-lock.json | @cyclonedx/cyclonedx-npm | npm audit |
| pnpm | pnpm-lock.yaml | cyclonedx-node-pnpm | pnpm audit |
| yarn Berry | yarn.lock | cyclonedx-yarn | yarn npm audit |
モノレポ(Turborepo / Nx)では ワークスペースごとに SBOM を生成し、ルートで merge するか、Dependency-Track 上で プロジェクト分離 する。
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"security:sbom": {
"dependsOn": ["^build"],
"outputs": ["dist/sbom.cyclonedx.json"]
}
}
}
よくある失敗とトラブルシューティング
| 症状 | 対処 |
|---|---|
| npm audit が 0 だが OSV が CVE を報告 | advisory 登録ラグ。OSV を正とし Dependabot alert を確認 |
| cyclonedx-npm が OOM | Node --max-old-space-size=8192。巨大 monorepo は workspace 分割 |
| Dependabot PR が CI で落ちる | semver major の breaking change。グループ化せず個別対応 |
| SBOM の purl がスキャナと不一致 | lockfile 再生成。private registry は purl の namespace を明示 |
| ignore-scripts でビルド失敗 | esbuild 等を allowlist。Docker 多段 build で devDep を除外 |
| transitive dep の CVE が直らない | overrides(npm)/ resolutions(yarn)で強制バンプ |
package.json overrides で transitive CVE を強制修正
{
"overrides": {
"semver": "^7.6.0",
"ws": "^8.17.1"
}
}
override は 最終手段 だ。upstream が修正版を出したら override を外し、Dependabot に任せる。
2026年チェックリスト:サプライチェーンセキュリティ成熟度
package-lock.json を必ずコミットし、npm ci --ignore-scripts を CI で使用
npm run sbom で CycloneDX 1.6 を生成し、リリース artifact に添付
npm audit + OSV Scanner を PR Required Check に設定
.github/dependabot.yml で npm と GitHub Actions を週次更新
Critical CVE に 72h / High に 14d の SLA を定義し GitHub Projects で追跡
修正不能 CVE は VEX を CycloneDX に付記し、CSP・セキュリティヘッダーで暫定緩和
四半期ごとに SBOM・ignore リスト・override を棚卸し
関連記事
あわせて読むと理解が深まる関連記事をまとめました。
| トピック | 記事 |
|---|---|
| Monorepo Turborepo Remote Cache 設計完全ガイド | Monorepo Turborepo Remote Cache 設計完全ガイド|CI パイプライン・GitHub Actions・2026 実践 |
| OpenAPI 3.1仕様のCIバリデーション完全ガイド | OpenAPI 3.1仕様のCIバリデーション完全ガイド|Spectral Lint・Breaking Change検出・GitHub Actions |
| CSP Report-Only 段階導入ガイド | CSP Report-Only 段階導入ガイド|本番を壊さずポリシーを検証する |
| 構造化ログ(JSON)とCorrelation ID設計 | 構造化ログ(JSON)とCorrelation ID設計|Pino/Winston + Loki/Grafana 実装ガイド |
| YAML JSON 変換 | YAML JSON 変換|設定ファイルの相互変換 |
| JSON CSV 相互変換 | JSON CSV 相互変換|Excel 連携のコツ |
| クリティカルレンダリングパス最適化 | クリティカルレンダリングパス最適化|FCP・LCPを改善する実践ガイド |
| JSONとCSVの相互変換 | JSONとCSVの相互変換|どちらを選ぶべきか?用途と違い |
| JSON Formatter Validate | JSON Formatter Validate|構文エラーの読み方 |
| JSON 整形ツールの使い方 | JSON 整形ツールの使い方|オンラインで安全に整形・圧縮 |
| JSONの「Unexpected token」エラー原因と対処法 | JSONの「Unexpected token」エラー原因と対処法 |
| Markdown Table GitHub Notion 互換性 | Markdown Table GitHub Notion 互換性 |
まとめ
依存関係脆弱性管理は、単発の npm audit では足りない。SBOM CycloneDX で「何が入っているか」を可視化し、npm audit と OSV Scanner で「既知の穴」を継続的に検知し、GitHub Dependabot で修正 PR を自動化する——この3点セットが2026年の npm プロジェクトの基盤だ。
その上で、修正版がない CVE には VEX で影響評価を明示し、セキュリティヘッダー と CSP による多層防御で暫定リスクを下げる。Sigstore provenance や SLSA は、エンタープライズ顧客・規制産業向けの 信頼の証明 として段階的に導入すればよい。
本記事の GitHub Actions workflow と .github/dependabot.yml をそのままコピーし、scripts/check-audit.mjs を追加すれば、今日から SBOM 付き脆弱性 CI を走らせられる。サプライチェーンセキュリティは「完璧なゼロ脆弱性」ではなく、検知速度・修正速度・説明責任 の3指標で改善を続けるものだ。
よくある質問(FAQ)
SBOM はどのタイミングで生成すべきですか?
毎 PR と リリースタグ の両方だ。PR 生成 SBOM は review 用 diff のベースライン、リリース SBOM は顧客・監査・インシデント対応用の 公式記録 になる。同一 lockfile から --output-reproducible で再生成可能であることを CI で検証すると、artifact の改ざん検知にも使える。
private npm パッケージは SBOM に含まれますか?
含まれる。@scope/private-pkg も purl として列挙される。ただし バージョンと hash が外部に漏れるため、SBOM artifact のアクセス制御(GitHub Environment secrets、private S3)は必須だ。public リポジトリに private パッケージ名を出したくない場合は、SBOM を internal artifact のみに保存する。
Dependabot と Renovate はどちらが良いですか?
2026年時点では GitHub ネイティブの Dependabot がセキュリティアラート・SARIF 連携・auto-merge エコシステムで手軽だ。高度な grouping、regex manager、複雑 monorepo 設定が必要なら Renovate が柔軟。どちらも npm audit / OSV とは独立して lockfile 更新 PR を作る点は同じ。
OSV Scanner の --ignore-vulns は監査で問題になりませんか?
VEX またはチケット番号とセット なら問題にならない。ignore は「見なかったことにする」ではなく「影響評価済みで受容」であることを PR コメント・VEX JSON・Security タブの Dismiss 理由に残す。四半期レビューで ignore 一覧を空に近づける KPI を置く。
コンテナイメージも SBOM 対象にすべきですか?
はい。Node アプリを Docker 化している場合、アプリ SBOM(CycloneDX npm) と イメージ SBOM(Syft / Trivy) の2層を用意する。ベースイメージ(node:20-alpine)の OS パッケージ CVE も Trivy で別途スキャンする。Kubernetes デプロイでは OCI artifact として SBOM を registry に同梱する運用が増えている。