依存関係脆弱性管理と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 を棚卸し

関連記事

あわせて読むと理解が深まる関連記事をまとめました。

トピック記事
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 ValidateJSON Formatter Validate|構文エラーの読み方
JSON 整形ツールの使い方JSON 整形ツールの使い方|オンラインで安全に整形・圧縮
JSONの「Unexpected token」エラー原因と対処法JSONの「Unexpected token」エラー原因と対処法
Markdown Table GitHub Notion 互換性Markdown Table GitHub Notion 互換性

まとめ

依存関係脆弱性管理は、単発の 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 に同梱する運用が増えている。