依存関係のスキャン

GitLab Ultimate10.7から導入されました

依存関係スキャニングは、アプリケーションの開発者とテスト者が、アプリケーションの開発中やテスト中に、依存関係のセ キュリティ脆弱性を自動的に発見するのに役立ちます。

概要

GitLab CI/CDを使用している場合、依存関係スキャンを使用して既知の脆弱性について依存関係を分析することができます。 すべての依存関係は、推移的依存関係(ネストされた依存関係としても知られています)を含めてスキャンされます。 既存の.gitlab-ci.yml ファイルに依存関係スキャンのテンプレートを含めるかAuto DevOpsが提供するAuto Dependency Scanningを暗黙的に使用することで、依存関係スキャンを利用することができます。

GitLab は Dependency Scanning レポートをチェックし、見つかった脆弱性をソースブランチとターゲットブランチの間で比較し、マージリクエストに情報を表示します。

Dependency Scanning Widget

結果は脆弱性の深刻度順にソートされます:

  1. クリティカル
  2. 高い
  3. ミディアム
  4. 低い
  5. 不明
  6. その他すべて

要件

Dependency Scanningジョブを実行するには、デフォルトでは、GitLab Runnerにdocker またはkubernetes のexecutorが必要です。GitLab.comの共有Runnerを使用している場合、デフォルトで有効になっています。

注意:独自のRunnerを使用する場合はインストールされているDockerのバージョンが19.03.0。 詳細はトラブルシューティング情報を参照してください。

GitLab 13.0からは、Dependency ScanningのためにDocker-in-Dockerを有効にしている場合のみ、Docker特権モードが必要です。

対応言語とパッケージマネージャ

GitLab はrules に依存して、リポジトリで検出された言語に応じて関連するアナライザを起動します。現在の検出ロジックでは、最大検索深度を2段階に制限しています。例えば、リポジトリにGemfileまたはapi/Gemfile ファイルが含まれている場合、gemnasium-dependency_scanning ジョブは有効になりますが、サポートされている依存ファイルがapi/client/Gemfileのみの場合は有効になりません。

以下の言語と依存関係マネージャーがサポートされています:

言語 (パッケージマネージャ) 対応ファイル スキャンツール
Java(Gradle、Maven) build.gradlebuild.gradle.ktspom.xml ジェムナジウム
JavaScript(npm,yarn) package-lock.jsonnpm-shrinkwrap.jsonyarn.lock Gemnasium,Retire.js
Go(Golang) go.sum ジェムナジウム
PHP(Composer) composer.lock ジェムナジウム
Python(setuptools,pip,Pipenv) setup.pyrequirements.txt, , 、requirements.piprequires.txtPipfile ジェムナジウム
Ruby(バンドラー) Gemfile.lock,gems.locked Gemnasiumbundler-audit
Scala(sbt) build.sbt ジェムナジウム

以下の言語、依存性マネージャ、依存性ファイルをサポートする計画が進行中です。 詳細はそれぞれのイシューリンクをご覧ください。

言語 (パッケージマネージャ) 対応ファイル スキャンツール イシュー
Python(詩) poetry.lock ジェムナジウム GitLab#7006
Python(Pipenv) Pipfile.lock ジェムナジウム GitLab#11756

貢献するスキャナー

他のセキュリティスキャナをGitLabにインテグレーションする方法については、セキュリティスキャナのインテグレーションドキュメントをご覧ください。

設定

GitLab 11.9以降で依存性スキャンを有効にするには、GitLabインストールの一部として提供されているDependency-Scanning.gitlab-ci.yml テンプレート含める必要があります。11.9より前のバージョンのGitLabでは、そのテンプレートで定義されているジョブをコピーして使用することができます。

.gitlab-ci.yml ファイルに以下を追加してください:

include:
  - template: Dependency-Scanning.gitlab-ci.yml

付属のテンプレートは、CI/CDパイプラインにDependency Scanningジョブを作成し、プロジェクトのソースコードに脆弱性がないかスキャンします。 結果はDependency Scanningレポートのアーティファクトとして保存され、後でダウンロードして分析することができます。 実装の制限により、常に最新のDependency Scanningアーティファクトを使用します。

依存関係スキャンの設定のカスタマイズ

依存関係スキャンの設定は、.gitlab-ci.ymlvariables パラメータを使用して環境変数で変更できます:

include:
  - template: Dependency-Scanning.gitlab-ci.yml

variables:
  DS_PYTHON_VERSION: 2

templateはパイプライン設定の前に評価されるため、変数の最後の記述が優先されます。

依存関係スキャンのジョブの上書き

Deprecation:GitLab 13.0から、onlyexceptの使用はサポートされなくなりました。テンプレートをオーバーライドする場合は、代わりに](../../../ci/yaml/README.md#rules) を使用する必要があります。

ジョブ定義をオーバーライドするには (例えば、variablesdependenciesのようなプロパティを変更するには)、オーバーライドするジョブと同じ名前の新しいジョブを宣言します。 この新しいジョブをテンプレートインクルードの後に配置し、その下に追加のキーを指定します。 例えば、これはgemnasium アナライザーのDS_REMEDIATE を無効にします:

include:
  - template: Dependency-Scanning.gitlab-ci.yml

gemnasium-dependency_scanning:
  variables:
    DS_REMEDIATE: "false"

利用可能な変数

依存関係スキャンは環境変数を使って設定できます。

依存関係スキャンの設定

以下の変数により、グローバル依存性スキャン設定を構成できます。

環境変数 説明
SECURE_ANALYZERS_PREFIX 公式のデフォルトイメージ (プロキシ) を提供する Docker レジストリの名前を上書きします。アナライザのカスタマイズについての詳細はこちらをご覧ください。
DS_DEFAULT_ANALYZERS 公式のデフォルト・イメージの名前をオーバーライドします。アナライザーのカスタマイズについて、詳しくはこちらをご覧ください。
DS_DISABLE_DIND Docker-in-Dockerを無効にし、アナライザを個別に実行します。この変数はデフォルトでtrue
ADDITIONAL_CA_CERT_BUNDLE 信頼するCA証明書のバンドル。
DS_EXCLUDED_PATHS パスに基づいて脆弱性を出力から除外します。 パターンのカンマ区切りリスト。 パターンは、グロブ、またはファイルやフォルダのパス (例えば、doc,spec) です。 親ディレクトリもパターンに一致します。 デフォルト:"spec, test, tests, tmp"
SECURE_LOG_LEVEL デフォルトのログレベルはinfoで、次の文字列のいずれかに設定できます:fatal,error,warn,info,debug

Docker-in-Dockerオーケストレータの設定

以下の変数はDocker-in-Dockerオーケストレータを設定するため、Docker-in-Dockerモードが有効な場合にのみ使用されます。

環境変数 デフォルト 説明
DS_ANALYZER_IMAGES   カンマで区切られたカスタムイメージのリスト。 公式デフォルトのイメージは有効のままです。アナライザーのカスタマイズについてはこちらをご覧ください。
DS_ANALYZER_IMAGE_TAG   公式のデフォルトイメージのDockerタグをオーバーライドします。アナライザーのカスタマイズについてはこちらをご覧ください。
DS_PULL_ANALYZER_IMAGES   Dockerレジストリからイメージを取り出します(0 に設定すると無効になります)。
DS_DOCKER_CLIENT_NEGOTIATION_TIMEOUT 2m Dockerクライアントネゴシエーションの制限時間。 タイムアウトはGoのParseDurationを使って解析されます。 有効な時間単位はns,us (またはµs)、ms,s,m, またはhです。 例えば、300ms,1.5h, または2h45m
DS_PULL_ANALYZER_IMAGE_TIMEOUT 5m アナライザーの画像を引き出す際の制限時間。 タイムアウトはGoのParseDurationを使用して解析されます。 有効な時間単位は、nsus (またはµs)、mssm、またはh。例えば、300ms1.5h、または2h45m
DS_RUN_ANALYZER_TIMEOUT 20m アナライザ実行時の制限時間。 タイムアウトはGoのParseDurationを使用して解析されます。 有効な時間単位は、nsus (またはµs)、mssm、またはhです。 たとえば、300ms1.5h、または2h45mです。

依存性スキャンで使用する特定のアナライザの設定

以下の変数は、特定の解析器(特定の言語/フレームワークで使用)を設定するために使用します。

環境変数 アナライザー デフォルト 説明
GEMNASIUM_DB_LOCAL_PATH gemnasium /gemnasium-db ローカルGemnasiumデータベースへのパス。
GEMNASIUM_DB_REMOTE_URL gemnasium https://gitlab.com/gitlab-org/security-products/gemnasium-db.git Gemnasiumデータベースを取得するためのリポジトリURL。
GEMNASIUM_DB_REF_NAME gemnasium master リモートリポジトリデータベースのブランチ名。GEMNASIUM_DB_REMOTE_URL が必要です。
DS_REMEDIATE gemnasium "true" 脆弱性のある依存関係の自動修復を有効にします。
PIP_INDEX_URL gemnasium-python https://pypi.org/simple Python パッケージインデックスのベース URL。
PIP_EXTRA_INDEX_URL gemnasium-python   PIP_INDEX_URLに加えて使用するパッケージインデックスの追加 URLの配列。 カンマ区切り。
PIP_REQUIREMENTS_FILE gemnasium-python   スキャンする Pip 要件ファイル。
DS_PIP_VERSION gemnasium-python   特定のpipバージョン(例:"19.3")のインストールを強制します。そうでない場合は、Dockerイメージにインストールされているpipが使用されます。(GitLab 12.7で導入)
DS_PIP_DEPENDENCY_PATH gemnasium-python   Python pip の依存関係を読み込むパス。(GitLab 12.2 で導入)
DS_PYTHON_VERSION retire.js   Pythonのバージョン。 2に設定すると、依存関係はPython 3.6の代わりにPython 2.7でインストールされます
DS_JAVA_VERSION gemnasium-maven 11 Javaのバージョン。利用可能なバージョン:8,11,13,14. MavenとGradleは、この値で指定されたJavaバージョンを使用します。
MAVEN_CLI_OPTS gemnasium-maven "-DskipTests --batch-mode" アナライザがmaven に渡すコマンドライン引数のリスト。非公開リポジトリの使用例を参照してください。
GRADLE_CLI_OPTS gemnasium-maven   アナライザからgradle に渡されるコマンドライン引数のリスト。
SBT_CLI_OPTS gemnasium-maven   アナライザーがsbtに渡すコマンドライン引数のリスト。
BUNDLER_AUDIT_UPDATE_DISABLED bundler-audit "false" bundler-audit アナライザの自動更新を無効にします。オフラインのエアギャップ環境で依存性スキャンを実行する場合に便利です。
BUNDLER_AUDIT_ADVISORY_DB_URL bundler-audit https://github.com/rubysec/ruby-advisory-db bundler-auditが使用する勧告データベースのURL。
BUNDLER_AUDIT_ADVISORY_DB_REF_NAME bundler-audit master BUNDLER_AUDIT_ADVISORY_DB_URLで指定された勧告データベースの git 参照。
RETIREJS_JS_ADVISORY_DB retire.js https://raw.githubusercontent.com/RetireJS/retire.js/master/repository/jsrepository.json retire.js JS脆弱性データファイルへのパスまたはURL。 データファイルをホストするURLが、オフラインインストールなどでカスタムSSL証明書を使用する場合は、ADDITIONAL_CA_CERT_BUNDLE 環境変数で証明書を渡すことができることに注意してください。
RETIREJS_NODE_ADVISORY_DB retire.js https://raw.githubusercontent.com/RetireJS/retire.js/master/repository/npmrepository.json retire.js ノード脆弱性データファイルへのパスまたは URL。 データファイルをホストする URL が、オフラインインストールなどでカスタム SSL 証明書を使用する場合は、ADDITIONAL_CA_CERT_BUNDLE 環境変数で証明書を渡すことができることに注意してください。
RETIREJS_ADVISORY_DB_INSECURE retire.js false 安全でない、または自己署名の SSL(TLS) 証明書を使用しているホストから、リモートの JS および Node 脆弱性データファイル (RETIREJS_JS_ADVISORY_DB およびRETIREJS_NODE_ADVISORY_DB 変数で定義) をフェッチできるようにします。

非公開Mavenリポジトリの使用

非公開 Maven リポジトリにログイン認証が必要な場合は、MAVEN_CLI_OPTS 環境変数を使用できます。

非公開Mavenリポジトリの使用方法の詳細はこちらをご覧ください。

Docker-in-Dockerの有効化

GitLab Ultimate 12.5で導入されました

必要であれば、Docker-in-Dockerを有効にして、GitLab 13.0以前の依存性スキャンの動作を復元することができます:

  1. 特権モードでDocker-in-Dockerを使用してGitLab Runnerを設定します。
  2. DS_DISABLE_DIND 変数をfalseに設定:

    include:
      - template: Dependency-Scanning.gitlab-ci.yml
    
    variables:
      DS_DISABLE_DIND: "false"
    

これにより、CI/CDパイプラインに複数の<analyzer-name>-dependency_scanning ジョブではなく、単一のdependency_scanning ジョブが作成されます。

脆弱性との対話

脆弱性が見つかったら、その脆弱性と対話することができます。 脆弱性と対話する方法については、こちらをお読みください。

脆弱性の解決(自動修復)

脆弱性の中には、GitLabが自動的に生成する解決策を適用することで修正できるものもあります。 脆弱性の解決策についてはこちらをご覧ください。

セキュリティダッシュボード

セキュリティダッシュボードは、グループ、プロジェクト、パイプラインに存在するすべてのセキュリティ脆弱性の概要を把握するのに適した場所です。セキュリティダッシュボードについてもっと読む。

脆弱性データベースの更新

脆弱性データベースの更新の詳細については、メンテナンステーブルを確認してください。

依存関係リスト

依存関係スキャンのさらなる利点は、プロジェクトの依存関係とその既知の脆弱性を表示できることです。依存関係リストについてもっと読む。

JSON形式のレポーター

依存関係スキャンツールは、JSON レポートファイルを出力します。 詳細については、このレポートのスキーマを参照してください。

依存関係スキャンレポートの例です:

{
  "version": "2.0",
  "vulnerabilities": [
    {
      "id": "51e83874-0ff6-4677-a4c5-249060554eae",
      "category": "dependency_scanning",
      "name": "Regular Expression Denial of Service",
      "message": "Regular Expression Denial of Service in debug",
      "description": "The debug module is vulnerable to regular expression denial of service when untrusted user input is passed into the `o` formatter. It takes around 50k characters to block for 2 seconds making this a low severity issue.",
      "severity": "Unknown",
      "solution": "Upgrade to latest versions.",
      "scanner": {
        "id": "gemnasium",
        "name": "Gemnasium"
      },
      "location": {
        "file": "yarn.lock",
        "dependency": {
          "package": {
            "name": "debug"
          },
          "version": "1.0.5"
        }
      },
      "identifiers": [
        {
          "type": "gemnasium",
          "name": "Gemnasium-37283ed4-0380-40d7-ada7-2d994afcc62a",
          "value": "37283ed4-0380-40d7-ada7-2d994afcc62a",
          "url": "https://deps.sec.gitlab.com/packages/npm/debug/versions/1.0.5/advisories"
        }
      ],
      "links": [
        {
          "url": "https://nodesecurity.io/advisories/534"
        },
        {
          "url": "https://github.com/visionmedia/debug/issues/501"
        },
        {
          "url": "https://github.com/visionmedia/debug/pull/504"
        }
      ]
    },
    {
      "id": "5d681b13-e8fa-4668-957e-8d88f932ddc7",
      "category": "dependency_scanning",
      "name": "Authentication bypass via incorrect DOM traversal and canonicalization",
      "message": "Authentication bypass via incorrect DOM traversal and canonicalization in saml2-js",
      "description": "Some XML DOM traversal and canonicalization APIs may be inconsistent in handling of comments within XML nodes. Incorrect use of these APIs by some SAML libraries results in incorrect parsing of the inner text of XML nodes such that any inner text after the comment is lost prior to cryptographically signing the SAML message. Text after the comment therefore has no impact on the signature on the SAML message.\r\n\r\nA remote attacker can modify SAML content for a SAML service provider without invalidating the cryptographic signature, which may allow attackers to bypass primary authentication for the affected SAML service provider.",
      "severity": "Unknown",
      "solution": "Upgrade to fixed version.\r\n",
      "scanner": {
        "id": "gemnasium",
        "name": "Gemnasium"
      },
      "location": {
        "file": "yarn.lock",
        "dependency": {
          "package": {
            "name": "saml2-js"
          },
          "version": "1.5.0"
        }
      },
      "identifiers": [
        {
          "type": "gemnasium",
          "name": "Gemnasium-9952e574-7b5b-46fa-a270-aeb694198a98",
          "value": "9952e574-7b5b-46fa-a270-aeb694198a98",
          "url": "https://deps.sec.gitlab.com/packages/npm/saml2-js/versions/1.5.0/advisories"
        },
        {
          "type": "cve",
          "name": "CVE-2017-11429",
          "value": "CVE-2017-11429",
          "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-11429"
        }
      ],
      "links": [
        {
          "url": "https://github.com/Clever/saml2/commit/3546cb61fd541f219abda364c5b919633609ef3d#diff-af730f9f738de1c9ad87596df3f6de84R279"
        },
        {
          "url": "https://github.com/Clever/saml2/issues/127"
        },
        {
          "url": "https://www.kb.cert.org/vuls/id/475445"
        }
      ]
    }
  ],
  "remediations": [
    {
      "fixes": [
        {
          "id": "5d681b13-e8fa-4668-957e-8d88f932ddc7",
        }
      ],
      "summary": "Upgrade saml2-js",
      "diff": "ZGlmZiAtLWdpdCBhL...OR0d1ZUc2THh3UT09Cg==" // some content is omitted for brevity
    }
  ]
}

バージョン管理とリリースプロセス

リリースプロセスのドキュメントを確認してください。

脆弱性データベースへの貢献者

gemnasium-dbプロジェクトを検索して、Gemnasium データベースの脆弱性を見つけることができます。 また、新しい脆弱性を投稿することもできます。

オフライン環境での依存関係スキャンの実行

インターネットを通じた外部リソースへのアクセスが制限されている、制限されている、または断続的な環境にある自己管理型 GitLab インスタンスでは、依存関係スキャンのジョブを正常に実行するためにいくつかの調整が必要です。 詳細については、オフライン環境を参照してください。

オフライン依存性スキャンの要件

以下は、オフライン環境で依存関係スキャンを使用するための要件です:

**pull policy 注意:**GitLab Runnerのデフォルトのalways、つまりRunnerはローカルに利用可能なDockerイメージがある場合でも、GitLabコンテナレジストリからDockerイメージをプルしようとします。ローカルに利用可能なDockerイメージのみを使用したい場合は、オフライン環境でGitLab Runnerのpull_policyif-not-presentに設定することができます。 しかし、CI/CDパイプラインで更新されたスキャナを使用することができるため、オフライン環境でない場合はプルポリシーの設定を](https://docs.gitlab.com/runner/executors/docker.html#using-the-always-pull-policy) に維持することをお勧めします。

GitLab Dependency ScanningのアナライザーイメージをDockerレジストリで利用可能にします。

サポートされているすべての言語とフレームワークで依存性スキャンを行うには、registry.gitlab.com から以下のデフォルトの依存性スキャンアナライザイメージをローカルの Docker コンテナレジストリにインポートします:

registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium:2
registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven:2
registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python:2
registry.gitlab.com/gitlab-org/security-products/analyzers/retire.js:2
registry.gitlab.com/gitlab-org/security-products/analyzers/bundler-audit:2

DockerイメージをローカルのオフラインDockerレジストリにインポートするプロセスは、ネットワークセキュリティポリシーに依存します。 外部リソースをインポートしたり、一時的にアクセスしたりすることができる、受け入れられ承認されたプロセスを見つけるために、IT担当者に相談してください。 これらのスキャナは定期的に新しい定義で更新されるため、定期的な更新を自分で行うことができるかどうかを検討してください。

Dockerイメージをファイルとして保存・転送する方法の詳細については、Dockerのドキュメントdocker save,docker load,docker export,docker importを参照してください。

Dependency Scanning CI ジョブ変数にローカル Dependency Scanning アナライザを使用するように設定します。

.gitlab-ci.yml ファイルに以下の設定を追加します。SECURE_ANALYZERS_PREFIX を、ローカルの Docker コンテナレジストリを参照するように置き換える必要があります:

include:
  - template: Dependency-Scanning.gitlab-ci.yml

variables:
  SECURE_ANALYZERS_PREFIX: "docker-registry.example.com/analyzers"
  GEMNASIUM_DB_REMOTE_URL: "gitlab.example.com/gemnasium-db.git"
  GIT_SSL_NO_VERIFY: "true"

上記の変数については、コンフィギュレーション・セクションの説明を参照してください。

言語とパッケージマネージャの固有設定

特定の言語とパッケージ・マネージャーの設定については、以下のセクションを参照してください。

JavaScript(npmとyarn)プロジェクト

.gitlab-ci.ymlの変数セクションに以下を追加:

RETIREJS_JS_ADVISORY_DB: "example.com/jsrepository.json"
RETIREJS_NODE_ADVISORY_DB: "example.com/npmrepository.json"

Ruby (gem) プロジェクト

.gitlab-ci.ymlの変数セクションに以下を追加:

BUNDLER_AUDIT_ADVISORY_DB_REF_NAME: "master"
BUNDLER_AUDIT_ADVISORY_DB_URL: "gitlab.example.com/ruby-advisory-db.git"

Python (setuptools)

PyPi の非公開リポジトリに自己署名証明書を使用する場合、(上記のテンプレート.gitlab-ci.yml 以外に)追加のジョブ設定は必要ありません。 しかし、setup.py を更新して、非公開リポジトリに到達できるようにする必要があります。以下は設定の例です:

  1. setup.py を更新して、install_requires リストの依存関係ごとに、非公開リポジトリを指すdependency_links 属性を作成します:

    install_requires=['pyparsing>=2.0.3'],
    dependency_links=['https://pypi.example.com/simple/pyparsing'],
    
  2. リポジトリURLから証明書を取得し、プロジェクトに追加します:

    echo -n | openssl s_client -connect pypi.example.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > internal.crt
    
  3. setup.py を新しくダウンロードした証明書に向けます:

    import setuptools.ssl_support
    setuptools.ssl_support.cert_paths = ['internal.crt']
    

制限事項

JavaScript プロジェクトでパスを使ったローカル依存関係の参照

Retire.jsアナライザーは、JavaScript プロジェクトのpackage.json 内のローカルパスによる依存性参照をサポートしていません。依存性スキャンは、このような参照に対して以下のエラーを出力します:

ERROR: Could not find dependencies: <dependency-name>. You may need to run npm install

回避策として、retire.js アナライザをDS_DEFAULT_ANALYZERSから削除します。

トラブルシューティング

Error response from daemon: error processing tar file: docker-tar: relocation error

このエラーは、依存関係スキャンジョブを実行するDockerのバージョンが19.03.00.である場合に発生します。 Docker19.03.1 以上に更新することを検討してください。古いバージョンは影響を受けません。この問題の.