依存関係脆弱性管理とSBOM CycloneDXガイド|npm audit・OSV・Dependabot・サプライチェーンセキュリティ2026

セキュリティ SBOM CycloneDX npm Dependabot サプライチェーン DevSecOps
結論
  • 依存関係脆弱性管理の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年にかけて、サプライチェーン攻撃は typosquattinglodashl0dash)、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 auditOSV(Open Source Vulnerabilities)GitHub Dependabot を組み合わせた実務パイプラインを、コピペ可能な YAML / CLI 例付きで解説します。最後に セキュリティヘッダー一覧CSP 設定ガイド への接続——依存パッケージの穴をアプリ層でどう補うか——も触れる。

1

package-lock.json をコミットし、npm ci を CI の唯一のインストール手段に固定する

2

@cyclonedx/cyclonedx-npm を devDependency に追加し、npm run sbom で CycloneDX JSON を生成する

3

npm audit --audit-level=high と OSV Scanner を GitHub Actions で pull_request 時に実行する

4

.github/dependabot.yml で npm と GitHub Actions の週次更新を有効化する

5

Critical/High CVE は Dependency-Track または GitHub Security タブで triage し、SLA を設定する

6

リリース時に SBOM を artifacts として保存し、Sigstore cosign で署名する(任意)

7

修正不能な 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.6VEX、コンポーネント hash、依存グラフCI 生成・Dependency-Track 連携
SPDX 2.3 / 3.0ライセンスコンプライアンスに強い法務・OSS 監査向け
Syft SBOMコンテナイメージ向けDocker レイヤ + npm の複合

CycloneDX の components 配列には、各 npm パッケージが type: librarypurl(Package URL)、hashes(integrity)付きで列挙される。dependencies セクションで依存グラフも表現できます。

purl(Package URL)とは

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 ゲート
Critical72時間以内PR ブロック
High2週間以内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 を CI で自動実行しない

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-npmpackage-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 セキュリティアラートの運用

1

GitHub Security タブで Critical / High アラートを確認し、Dependabot PR が自動作成されているかチェック

2

PR の CI(npm audit、OSV、ユニットテスト、E2E)が green であることを確認

3

major 更新は CHANGELOG と breaking change を読み、必要なら feature ブランチで手動検証

4

merge 後、本番デプロイパイプラインで新 lockfile が反映されたことを確認

5

修正不能 CVE は VEX を発行し、Security タブで 'Dismiss' 理由を documented risk として記録

6

四半期ごとに 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改ざん防止 CIbranch protection + Required Check
Build L3署名付き provenancenpm —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-scriptspostinstall 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;
SBOM はアプリ層防御の代替にならない

CSP やヘッダーは 被害の限定(containment) であり、脆弱パッケージの 根治(remediation) ではありません。SBOM + Dependabot で根治を目指しつつ、暫定期間は多層防御でリスクを下げる——両輪で設計します。

インシデント対応 Runbook:CVE 公開から修正まで

1

GitHub Security / npm audit / OSV / Dependency-Track から Critical アラートを検知

2

CycloneDX SBOM で affected component の purl と依存経路(dependsOn)を特定

3

Dependabot PR または手動 bump で修正版へ更新。lockfile 差分を PR で review

4

修正版が無い場合: VEX 草案作成、機能影響調査、CSP/ヘッダー暫定強化を parallel 実行

5

merge 後、新 SBOM を artifact として保存し、顧客・社内ステークホルダーへ通知

6

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 を前提にしたが、概念は他パッケージマネージャにも移植できます。

マネージャlockfileSBOM ツールaudit 相当
npmpackage-lock.json@cyclonedx/cyclonedx-npmnpm audit
pnpmpnpm-lock.yamlcyclonedx-node-pnpmpnpm audit
yarn Berryyarn.lockcyclonedx-yarnyarn 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年チェックリスト:サプライチェーンセキュリティ成熟度

1

package-lock.json を必ずコミットし、npm ci --ignore-scripts を CI で使用

2

npm run sbom で CycloneDX 1.6 を生成し、リリース artifact に添付

3

npm audit + OSV Scanner を PR Required Check に設定

4

.github/dependabot.yml で npm と GitHub Actions を週次更新

5

Critical CVE に 72h / High に 14d の SLA を定義し GitHub Projects で追跡

6

修正不能 CVE は VEX を CycloneDX に付記し、CSP・セキュリティヘッダーで暫定緩和

7

四半期ごとに SBOM・ignore リスト・override を棚卸し

まとめ

依存関係脆弱性管理は、単発の npm audit では足りありません。SBOM CycloneDX で「何が入っているか」を可視化し、npm auditOSV 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 に同梱する運用が増えています。