Skip to main content

JavaScriptおよびNode.jsアプリケーションのSBOMを生成する方法

著者
Blog Header Vuln card blog

2023年5月22日

0 分で読めます

編集者注:2023年5月31日

Snykのsbomコマンドが一般提供されたことを受け、Snykを使ってSPDX仕様に準拠したSBOMを生成する方法を紹介する内容に更新しました。

SBOMとは何ですか?

SBOMはソフトウェア部品表(Software Bill of Materials)の略称で、プロジェクトを構成するすべてのオープンソースnpmパッケージを一覧にしたものです。ただし、オープンソースやソフトウェアパッケージに限らず、オペレーティングシステムのライブラリやマイクロサービスの一覧なども含めることができます。

npmソフトウェアパッケージは、2つのファイルに記述されます。直接依存関係を含むpackage.jsonと、JavaScriptまたはNode.jsアプリケーションのプロジェクトをビルドする際にインストールされる依存関係の全ツリーを表すpackage-lock.jsonやyarn.lockなどのロックファイルです。

Node.jsアプリケーションでSBOMを維持することが重要なのはなぜですか?

JavaScriptエコシステムでは、開発者に影響を及ぼすセキュリティインシデントが後を絶ちません。最近の例としては、抗議を目的としたソフトウェア(プロテストウェア)、ディスク上のデータを破損させることを狙った悪意あるマルウェアの一種や、依存関係の混乱攻撃を悪用して組織内部のコンピューターシステムに侵入する悪意あるnpmパッケージなどがあります。

オープンソースライブラリが広く利用され、npmなどのソフトウェアリポジトリでセキュリティインシデントが増加する今、アプリケーションで特定の依存関係のバージョンが使われているかを評価し、正確に特定できることが不可欠です。さらに、こうしたセキュリティリスクが高まるなか、依存関係のアップグレードを順次進めたり、短期間で検索・置換したりして、迅速に対応する必要性も増しています。

「ソフトウェアの構築に使用されるさまざまなコンポーネントの詳細とサプライチェーン上の関係を記録した正式な文書」— NIST(米国国立標準技術研究所)

開発者にとってSBOMは、技術スタックを構成する依存関係を包括的に把握できるため、古くなった依存関係や脆弱な依存関係を更新したり、修正がないパッケージや互換性のないライセンスを使用しているパッケージを置き換えたりするのに役立ちます。また、独自のユースケースに照らして、脆弱性を該当なしとして除外することもできます。さらに、サプライチェーンのセキュリティを追跡するための政府のサイバーセキュリティコンプライアンス要件により、セキュリティチームや運用チームからJavaScriptおよびNode.jsアプリケーションのSBOM生成を求められることもあるでしょう。

Snyk APIを使ってNode.jsアプリケーションのSBOMを生成する

Snykは、開発者向けにセキュリティ上の問題の検出と修正を自動化する、無料の開発者セキュリティプラットフォームです。Snykでプロジェクトを監視すれば、セキュリティ修正をタイムリーに適用できます。

現在、SBOM機能は有料プランのお客様のみご利用いただけます。有料プランをご利用の場合は、Node.jsアプリケーションのSBOM生成を始めましょう。

前提条件:

  • Snykの有料アカウント

  • Snyk APIへのアクセス

  • Snykプラットフォームにインポート済みのJavaScriptまたはNode.jsプロジェクト

  • curlコマンドラインツール

ステップ1:JavaScriptプロジェクトをSnykにインポートする

まず、プロジェクトをSnykプラットフォームにインポートします。これにより、含まれるすべてのnpm依存関係とライブラリをスキャン、監視、分析できます。

プロジェクトをインポートする手順はこちら(1分の簡単な動画もご覧いただけます)。

ステップ2:Snykトークンを準備する

SnykプラットフォームにAPIリクエストを送信するには、プロジェクトのSBOMレポート用エンドポイントを照会する権限を持つSnyk APIトークンが必要です。

Snyk CLIをお使いの場合、次のコマンドを実行するとSnyk APIトークンを確認できます。

$ snyk config get api

ただし、このSnyk APIトークンには、組織やプロジェクトにリクエストを送信する権限がない場合があります。そのため、このタスク専用の新しいサービスアカウントを作成し、CIなどのシステムから自動化することをおすすめします。

サービスアカウントを作成するには、組織の設定からサービスアカウントに移動し、新しいサービスアカウントの名前を入力して、Org Adminロールを割り当て、作成ボタンをクリックします。

Snykのサービスアカウント設定画面。Org Adminロールが設定された「service_account_for_sbom_report」という新しいサービスアカウントと、[作成]ボタンが表示されています。

APIトークンが表示されます。安全な場所に保存して、すぐ使えるようにしておきましょう。この後、Snyk APIにリクエストを送信してSBOMを生成する際に使用します。

詳しくは、Snykユーザードキュメントのサービスアカウントの管理をご覧ください。

ステップ3:組織IDとプロジェクトIDを確認する

同じ設定ページで組織IDを確認できます。コピーして、すぐ使えるようにしておきましょう。

「General」タブと、[Copy]ボタンが表示された「Organization ID」フィールドを含むSnykの組織設定ページ

次に、SnykにインポートしたJavaScriptプロジェクトのプロジェクトIDを取得します。

プロジェクトに移動し、SBOMを生成するプロジェクトを見つけて、クリックして詳細を表示します。

Dockerfile、package.json、コード分析プロジェクトを一覧表示し、インポート数、テスト数、問題数を示すセキュリティダッシュボード。

プロジェクトの詳細ページで、右上の設定タブをクリックし、下にスクロールしてプロジェクトIDをコピーします。

一般タブ、毎日のテスト頻度、プロジェクトID欄を表示したSnykプロジェクトの設定ページ。

ステップ4:curlとSnyk APIを使ってSBOMを生成する

この時点で、次の情報が揃っているはずです。

  • Snyk APIトークン

  • 組織ID

  • プロジェクトID

これでAPIリクエストを送信してSBOMレポートを取得できます。curlコマンドラインツールを使って、Snyk APIにHTTPリクエストを送信します。

curl -H "Authorization: token $SNYK_TOKEN" \
"https://api.snyk.io/rest/orgs/<ORG_ID>/projects/<PROJECT_ID>/sbom?version=2023-03-20&format=cyclonedx1.4%2Bjson"

APIから返される結果はJSON形式で、SBOMレポートにはCycloneDX規格が使用されます。APIクエリパラメーターの末尾にあるURLエンコードされた%2Bは、文字+をエンコードしたものです。

ヒント:複数のSBOM形式を受け取るには、formatクエリパラメーターを複数指定できます。

出力データが大きすぎたり、コンソールで読みづらかったりする場合は、パイプでjqに渡すと、見やすく整形できます。

curl -H "Authorization: token $SNYK_TOKEN" \
"https://api.snyk.io/rest/orgs/<ORG_ID>/projects/<PROJECT_ID>/sbom?version=2023-03-20&format=cyclonedx+json" | jq .

生成されたSBOMレポートは読みやすくなりました。JavaScriptのnpmパッケージマネージャーで管理されているプロジェクトをインポートした場合、次のような内容になります。

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "version": 1,
  "metadata": {
    "timestamp": "2023-02-21T11:01:07Z",
    "tools": [
      {
        "vendor": "Snyk",
        "name": "Snyk Open Source"
      }
    ],
    "component": {
      "bom-ref": "1-goof@1.0.1",
      "type": "application",
      "name": "goof",
      "version": "1.0.1",
      "purl": "pkg:npm/goof@1.0.1"
    },
    "properties": [
      {
        "name": "snyk:org_id",
        "value": "<REDACTED>"
      },
      {
        "name": "snyk:project_id",
        "value": "<REDACTED>"
      }
    ]
  },
  "components": [
    {
      "bom-ref": "2-adm-zip@0.4.7",
      "type": "library",
      "name": "adm-zip",
      "version": "0.4.7",
      "purl": "pkg:npm/adm-zip@0.4.7"
    },
    {
      "bom-ref": "3-bytes@1.0.0",
      "type": "library",
      "name": "bytes",
      "version": "1.0.0",
      "purl": "pkg:npm/bytes@1.0.0"
    },

生成されたSBOMレポートは有効なCycloneDX 1.4ドキュメントで、指定したSnykプロジェクトのソフトウェア部品表が含まれています。

豊富なメタデータに加え、推移的依存関係も報告され、依存元のライブラリが明らかになります。たとえば、先ほどと同じレポートには次のような情報が含まれます。

  {
      "ref": "63-utils-merge@1.0.0"
    },
    {
      "ref": "64-serve-static@1.9.3",
      "dependsOn": [
        "34-escape-html@1.0.1",
        "53-parseurl@1.3.3",
        "62-send@0.12.3",
        "63-utils-merge@1.0.0"
      ]
    },
    {
      "ref": "65-type-is@1.6.16",
      "dependsOn": [
        "6-media-typer@0.3.0",
        "37-mime-types@2.1.23"
      ]
    },

現時点でCycloneDX出力形式から確認できる情報は次のとおりです。

  • 直接依存関係

  • 推移的依存関係と、それらが依存するパッケージとの関係

  • このSBOMの生成対象となったSnykのOrgおよびProject識別子

  • 入力として指定したパッケージマニフェストファイルに情報があれば、このSBOMの生成対象となったアプリケーション名またはプロジェクト名

APIドキュメントでは、JSONの代わりにXMLでシリアル化する方法や、ソフトウェア部品表の標準であるSPDX仕様のドキュメントを出力する方法など、SBOM用Snyk APIのその他の利用方法をご確認いただけます。

これで、オープンソース依存関係のSBOM生成を自動化できるようになりました。次は何を作りますか?ぜひDevSecOps Discordコミュニティで教えてください。

Snyk CLIを使ってNode.jsアプリケーションのSBOMを生成する

Snyk APIに直接アクセスできない場合は、幅広いOSに対応したSnyk CLIを利用できます。静的コード解析からInfrastructure as Codeまで、Snykのすべての製品で問題の検出、修正、監視、レポート作成に使用できます。

パッケージマネージャーで管理されているJavaScriptアプリケーションのSBOMを生成してみましょう。

前提条件:

package.jsonマニフェストファイルがあるJavaScriptプロジェクトのディレクトリで、そのファイルを分析し、構成するすべてのソフトウェア部品を確認できます。

devDependencyにdebug、本番環境の依存関係としてWebアプリケーションフレームワークのfastifyを指定したNode.jsプロジェクトを例に考えてみましょう。

{
  "name": "my-sbom-learning-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "debug": "^4.3.4"
  },
  "dependencies": {
    "fastify": "^4.13.0"
  }
}

直接依存関係がわずか2つの場合、推移的依存関係はどれほどになるでしょうか。SBOMを生成すれば、プロジェクトの依存関係をすべて把握できます。次のsnykコマンドを実行すると、現在のディレクトリから対応するpackage.jsonファイルを探して分析します。

snyk sbom --format=cyclonedx1.4+json

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "version": 1,
  "metadata": {
    "timestamp": "2023-02-27T08:06:35Z",
    "tools": [
      {
        "vendor": "Snyk",
        "name": "Snyk Open Source"
      }
    ],
    "component": {
      "bom-ref": "1-a@1.0.0",
      "type": "application",
      "name": "a",
      "version": "1.0.0",
      "purl": "pkg:npm/a@1.0.0"
    }
  },
  "components": [
    {
      "bom-ref": "2-fast-deep-equal@3.1.3",
      "type": "library",
      "name": "fast-deep-equal",
      "version": "3.1.3",
      "purl": "pkg:npm/fast-deep-equal@3.1.3"
    },
    {
      "bom-ref": "3-json-schema-traverse@1.0.0",
      "type": "library",
      "name": "json-schema-traverse",
      "version": "1.0.0",
      "purl": "pkg:npm/json-schema-traverse@1.0.0"
    },

上記のCycloneDX出力は、記事が長くなりすぎないよう約40行で省略しています。直接依存関係がこれほど少ないプロジェクトでも、ソフトウェア部品表全体は整形済みJSONで749行になります。

jqを使って、このプロジェクトに含まれるオープンソース依存関係の数を数えられます。

snyk sbom --format=cyclonedx1.4+json | jq ".components | length"

このプロジェクトのソフトウェア部品表には、オープンソースパッケージが合計60個含まれていることがわかります。

ここでSBOMの重要性が明らかになります。セキュリティチームや政府の命令によるコンプライアンスや規制要件を満たすだけのものではありません。プロジェクトが直接インストールした2つだけでなく、実際には60個のオープンソースパッケージに依存していることがわかりました。ソフトウェアサプライチェーンに関わるこの問題は、セキュリティ上の影響が大きく、利用者に直接的なリスクをもたらします。

プロジェクトが実際には60個のオープンソースパッケージに依存しているとわかると、次のような疑問が浮かぶかもしれません。

  1. 組織のガイドラインや利用規定に準拠しないライセンスのパッケージは含まれていないか?

  2. これらのパッケージはすべて、現在も積極的にメンテナンスされているか?

  3. この60個のパッケージのいずれかに新たな脆弱性が見つかったら、どうなるか?

こうしたプロジェクトの健全性に関する懸念の解決に、私たちはSnyk Advisorを活用して取り組んできました。プロジェクトの人気度、メンテナンス状況、セキュリティ、コミュニティの各指標を考慮した健全性スコアを提供します。

datejs JavaScriptパッケージのSnyk Advisorページ。ヘルススコア53/100とパッケージのステータス詳細が表示されています。

SBOMの話に戻りましょう。プロジェクトをスキャンする際に利用できる、SBOMコマンドラインの全オプションを以下に示します。

$ snyk sbom --file=<file> --format=cyclonedx1.4+json [targetDirectory] 

SPDX仕様のSBOMを生成する

Snyk CLIとAPIは、SPDX仕様にも対応しています。formatコマンドラインフラグをspdx2.3+jsonに変更すると、SPDXに準拠したJSON形式のSBOMを生成できます。手順は次のとおりです。

$ snyk sbom --format=spdx2.3+json

これを実行すると、先ほど紹介したサンプルのFastifyプロジェクトでは、次のようなJSONレスポンスの一部が出力されます。

{
  "spdxVersion": "SPDX-2.3",
  "dataLicense": "CC0-1.0",
  "SPDXID": "SPDXRef-DOCUMENT",
  "name": "my-sbom-learning-project@1.0.0",
  "documentNamespace": "https://snyk.io/spdx/sbom-",
  "creationInfo": {
    "licenseListVersion": "3.19",
    "creators": [
      "Tool: Snyk Open Source",
      "Organization: Snyk"
    ],
    "created": "2023-05-30T12:09:22Z"
  },
  "packages": [
    {
      "name": "my-sbom-learning-project",
      "SPDXID": "SPDXRef-1-my-sbom-learning-project-1.0.0",
      "versionInfo": "1.0.0",
      "downloadLocation": "NOASSERTION",
      "copyrightText": "NOASSERTION",
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE-MANAGER",
          "referenceType": "purl",
          "referenceLocator": "pkg:npm/my-sbom-learning-project@1.0.0"
        }
      ]
    },
    {
      "name": "fastify",
      "SPDXID": "SPDXRef-2-fastify-4.17.0",
      "versionInfo": "4.17.0",
      "downloadLocation": "NOASSERTION",
      "copyrightText": "NOASSERTION",
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE-MANAGER",
          "referenceType": "purl",
          "referenceLocator": "pkg:npm/fastify@4.17.0"
        }
      ]
    },
    {
      "name": "@fastify/ajv-compiler",
      "SPDXID": "SPDXRef-3-fastify-ajv-compiler-3.5.0",
      "versionInfo": "3.5.0",
      "downloadLocation": "NOASSERTION",
      "copyrightText": "NOASSERTION",
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE-MANAGER",
          "referenceType": "purl",
          "referenceLocator": "pkg:npm/%40fastify/ajv-compiler@3.5.0"
        }
      ]
    },
    {
      "name": "ajv",
      "SPDXID": "SPDXRef-4-ajv-8.12.0",
      "versionInfo": "8.12.0",
      "downloadLocation": "NOASSERTION",
      "copyrightText": "NOASSERTION",
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE-MANAGER",
          "referenceType": "purl",
          "referenceLocator": "pkg:npm/ajv@8.12.0"
        }
      ]
    },

SBOMでほかに確認できる情報

Snykは、IDEでセキュリティ上の問題を含むコードを即座に検出したり、GitHubやBitbucket上のソフトウェアリポジトリに対して修正用のプルリクエストを自動作成したりすることで、開発者が安全なアプリケーションを構築・リリースできるよう支援しています。

この記事では、SBOMに含まれるインベントリの一部として、JavaScriptアプリケーションの依存関係に焦点を当てました。しかしSBOMには、プロジェクトで使用されるソフトウェアコンポーネントに関する、ほかにも役立つさまざまな情報が含まれています。こうした追加情報は、ソフトウェア製品の構成を把握するだけでなく、セキュリティリスク、コンプライアンス要件、ライセンスの管理にも不可欠です。SBOMで確認できる情報の例を以下に示します。

  1. コンポーネントの詳細:ソフトウェアで使用される各コンポーネントに関する情報です。npmパッケージ名、バージョン、配布元(npmjsリポジトリまたはGitHubリポジトリなど)が含まれます。

  2. ライセンス情報:ソフトウェアで使用される各コンポーネントに適用されるライセンスの種類、条件、義務などの詳細です。MITやApacheライセンスのnpmパッケージに慣れていても、依存関係の中に互換性のないGNU GPLなどのライセンスが含まれ、法的リスクが生じる可能性があります。

  3. 脆弱性データ:ソフトウェアで使用されるnpmパッケージに関連する、一般に公開されているセキュリティ脆弱性の情報です。直接的な影響だけでなく、間接的な影響も確認できます。

  4. 暗号データ:ソフトウェアで使用される暗号コンポーネントに関する情報です。アルゴリズムや鍵長などが含まれます。たとえば、アプリケーションで脆弱なMD5ハッシュなどの安全性に問題のあるアルゴリズムを使用している場合、それを把握し、必要な対策を講じることができます。

  5. ビルド情報:ビルド環境、使用したツール、ビルド設定など、ソフトウェアのビルド方法に関する詳細です。

  6. メタデータ:プロジェクト名、バージョン、作成者など、ソフトウェアに関連するその他の情報です。

JavaScript開発者にとってSBOMがどのように役立つか、具体例として次の表をご覧ください。

コンポーネント名

バージョン

ライセンスの種類

脆弱性データ

暗号データ

Express

4.4.0

MIT

該当なし

Lodash

4.17.16

MIT

該当なし

Vue

2.5.16

MIT

該当なし

Axios

0.21.0

MIT

該当なし

この記事の執筆時点で、Snykは次の形式で依存関係とその関係性を表示します。

  • CycloneDXバージョン1.4(JSON)

  • CycloneDXバージョン1.4(XML)

  • SPDXバージョン2.3(JSON)

現在、脆弱性やライセンスなど、ほかの仕様セクションへの対応にも取り組んでいます。

Snykでは、SBOMをほかの方法でも活用できます。

  • SBOMチェッカーツールは、SBOMファイルをアップロードすると、npmパッケージに含まれる脆弱性をSnykが検出する無料のウェブサイトです。

  • SBOMに関するSnyk APIセクション

  • Snyk CLI

  • SBOMのユーザードキュメントを詳しく見る

  • オープンソースプロジェクトのBomberは、SBOM仕様のフォーマットを入力として読み込み、脆弱性の一覧を出力できます。ベンダーのクローズドソースコンポーネントを扱う必要がある場合に役立つ可能性があり、脆弱性データの提供元としてSnykもサポートしています。

Java開発者の方、または組織内でJavaベースのアプリケーションを開発している方は、同僚のBrian VermeerによるMavenとGradleを使ってJavaでSBOMを作成する方法の記事をご覧ください。

より詳しい入門情報については、Snykの記事オープンソースのサプライチェーンセキュリティを支えるソフトウェア部品表(SBOM)をお読みください。

オープンソースの依存関係を安全に

開発者を第一に考えたSnykのツールなら、脆弱なオープンソースの依存関係やその推移的依存関係を、ワンクリックで修正するプルリクエストを作成できます。

続きを読む

blog feature snyk container custom base recommendations
Blog

Evo Agentic AppSecのご紹介:AI開発のスピードに対応するセキュリティ

AI駆動型開発のスピードに、従来のセキュリティワークフローは追いついていません。SnykのAgentic AppSecは、セキュリティエージェントが脆弱性を継続的に検出、修正、検証し、人が基準を定められるようにします。

blog feature ai violet
Blog

VulnBump:AIエージェントはビルドを壊さずに脆弱な依存関係を修正できるか?

VulnBumpは、実際の依存関係アップグレード307件を対象にAIエージェントをテストします。脆弱性が解消され、ビルドとテストが成功した場合にのみ、修正としてカウントされます。

Blog

フロンティアモデルは脆弱性を発見した。攻撃者だけがエクスプロイトチェーンを見つけた。

静的解析で欠陥は見つかりましたが、ライブ攻撃テストで侵害につながる連鎖を実証できたのは唯一でした。Evo COS、Claude Security、Claude Code Securityを比較します。