Secret DetectionとDependency Scanning
(トップページはこちら) - (アプリケーションのセキュリティを始める)
アプリケーション開発において、セキュリティインシデントの多くは、機密情報の漏洩と脆弱な依存関係の使用に起因します。GitLabのSecret DetectionとDependency Scanningは、これらのリスクを開発プロセスの早い段階で検出し、本番環境への影響を防ぎます。
本記事では、これらの機能の実装方法、カスタマイズ、組織全体への展開戦略を解説します。
1. Secret Detection: 機密情報の漏洩を防ぐ多層防御
1.1. なぜSecret Detectionが必要なのか
APIキー、トークン、秘密鍵などの機密情報が誤ってリポジトリにコミットされると、以下のリスクが発生します。
- 即座のセキュリティ侵害: リポジトリへのアクセス権を持つ全員が機密情報を閲覧可能
- 履歴からの削除困難: Gitの履歴に残るため、完全な削除には特別な手順が必要
- 自動化されたスキャン: 攻撃者は公開リポジトリを自動スキャンし、数分以内に機密情報を発見
GitLabのSecret Detectionは、これらのリスクを3つの異なるレイヤーで防ぎます。
1.2. 利用可能なプランと提供形態
- Tier: Free, Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
1.3. 3つの検出レイヤー
1.3.1. Secret Push Protection(プッシュ時の保護)
実行タイミング: コミットをGitLabにプッシュする際
動作: リアルタイムでシークレットをスキャンし、検出された場合はプッシュをブロックします。これにより、機密情報がリポジトリに到達する前に阻止できます。
利点: 最も早い段階での防御。履歴に残らないため、事後対応が不要
制限事項: スキップ可能(ただし、スキップした場合は記録される)
1.3.2. Pipeline Secret Detection(パイプライン検出)
実行タイミング: CI/CDパイプラインの一部として実行
動作:
- デフォルトブランチへのコミットをスキャン
- マージリクエストパイプラインで有効化すれば、開発ブランチもスキャン可能
利点: Push Protectionをスキップした場合のセーフティネット
1.3.3. Client-side Secret Detection(クライアント側検出)
実行タイミング: IssueやMerge Requestの説明文・コメント入力時
動作: GitLabに保存される前にシークレットを検出し、警告を表示
利点: コード以外の場所での機密情報漏洩も防止
1.4. 実装方法
1.4.1. 前提条件
-
.gitlab-ci.ymlファイルにtestステージが存在すること - GitLab Runner(docker または kubernetes executor)
1.4.2. 基本設定
.gitlab-ci.ymlにテンプレートを追加:
include:
- template: Jobs/Secret-Detection.gitlab-ci.yml
1.4.3. マージリクエストパイプラインでの実行
include:
- template: Jobs/Secret-Detection.gitlab-ci.yml
secret_detection:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
1.5. 除外設定
誤検出を減らすための除外設定:
variables:
SECRET_DETECTION_EXCLUDED_PATHS: "tests/, docs/, *.md"
1.6. 自動対応機能
GitLabは、検出されたシークレットに対して以下の対応を提供します。
- 脆弱性レポートへの記録: すべての検出されたシークレットを一元管理
- 自動無効化: 一部のシークレットタイプ(GitLab Personal Access Tokenなど)は自動的に無効化
- 修復ガイダンス: シークレットタイプごとの具体的な対応手順
2. Dependency Scanning: 依存関係の脆弱性を早期発見
2.1. なぜDependency Scanningが必要なのか
現代のアプリケーションは、平均して数百の依存関係を持ちます。これらの依存関係に脆弱性が存在すると、以下のリスクが発生します。
- 推移的依存関係の脆弱性: 直接使用していないライブラリの脆弱性も影響
- 既知の脆弱性の悪用: CVEデータベースに登録された脆弱性は攻撃者に知られている
- サプライチェーン攻撃: 依存関係を通じた攻撃の増加
2.2. 利用可能なプランと提供形態
- Tier: Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
2.3. 重要な変更情報
Gemnasiumアナライザーベースの依存関係スキャンは、GitLab 17.9で非推奨となり、GitLab 19.0で削除予定です。新しいDependency Scanning analyzerへの移行を推奨します。
2.4. 主要な特徴
2.4.1. 包括的なスキャン
特徴:
- 直接的な依存関係と推移的(ネストされた)依存関係の両方を分析
- 深さの制限なし(すべての階層を分析)
- 手動レビューでは見逃しがちなセキュリティ問題も検出
2.4.2. サポート言語とパッケージマネージャー
| 言語 | パッケージマネージャー | サポートファイル | 複数ファイル対応 |
|---|---|---|---|
| .NET / C# | NuGet | packages.lock.json |
✓ |
| C / C++ | Conan | conan.lock |
✓ |
| Go | Go Modules | go.mod |
✓ |
| Java / Kotlin | Gradle |
build.gradle, build.gradle.kts
|
✗ |
| Java / Kotlin | Maven | pom.xml |
✗ |
| JavaScript / TypeScript | npm |
package-lock.json, npm-shrinkwrap.json
|
✓ |
| JavaScript / TypeScript | yarn | yarn.lock |
✓ |
| JavaScript / TypeScript | pnpm | pnpm-lock.yaml |
✓ |
| PHP | Composer | composer.lock |
✓ |
| Python | pip |
requirements.txt, requirements.pip, requires.txt
|
✗ |
| Python | Pipenv |
Pipfile, Pipfile.lock
|
✗ |
| Python | Poetry | poetry.lock |
✗ |
| Python | setuptools | setup.py |
✗ |
| Python | uv | uv.lock |
✓ |
| Ruby | Bundler |
Gemfile.lock, gems.locked
|
✓ |
| Scala | sbt | build.sbt |
✗ |
| Swift | Swift Package Manager | Package.resolved |
✗ |
| Swift | CocoaPods | Podfile.lock |
✗ |
| Dart | Pub | pubspec.lock |
✗ |
注意事項:
- Java 21 LTSはsbt 1.9.7に制限
- GradleとJava 21はFIPSモードで非サポート
- pnpmはバンドル依存関係を保存しないため、報告される依存関係がnpmやyarnと異なる場合がある
2.5. 実装方法
2.5.1. 前提条件
-
.gitlab-ci.ymlファイルにtestステージが存在すること - GitLab Runner(docker または kubernetes executor)
- セルフマネージドRunnerの場合、上記executorが必要
- GitLab.comのSaaS Runnerでは自動的に有効
2.5.2. 方法1: 事前設定済みマージリクエストを使用
最も簡単な方法です。複雑な.gitlab-ci.ymlがない場合に推奨します。
- サイドバーからSecure > Security configurationを選択
- Dependency Scanning行でConfigure with a merge requestを選択
- Create merge requestを選択
- マージリクエストをレビューしてMergeを選択
2.5.3. 方法2: 手動で.gitlab-ci.ymlを編集
複雑なCI/CD設定がある場合に推奨します。
include:
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
2.5.4. 方法3: スキャン実行ポリシーを使用
グループレベルで一括設定する場合に推奨します。
name: "全プロジェクトでDependency Scanningを実施"
description: "すべてのマージリクエストでDependency Scanningを実行"
enabled: true
rules:
- type: pipeline
branches:
- main
- master
actions:
- scan: dependency_scanning
2.6. スキャン結果の確認
2.6.1. パイプラインでの確認
- サイドバーからBuild > Pipelinesを選択
- 対象のパイプラインを選択
- Securityタブを選択
- 脆弱性を選択して詳細を確認
2.6.2. 脆弱性情報の詳細
各脆弱性について、以下の情報が提供されます。
| 項目 | 説明 |
|---|---|
| Status | トリアージまたは解決済みかどうか |
| Description | 脆弱性の原因、潜在的な影響、推奨される修復手順 |
| Severity | 影響度に基づく6段階の重大度分類(Critical, High, Medium, Low, Info, Unknown) |
| CVSS score | 重大度に対応する数値スコア(0.0-10.0) |
| EPSS | 実際に悪用される可能性の指標(0.0-1.0) |
| Has Known Exploit (KEV) | 既知の悪用事例の有無 |
| Reachable | 脆弱な依存関係がコード内で実際に使用されているかの指標 |
| Scanner | 検出に使用されたアナライザー |
| Location | 脆弱な依存関係が含まれるファイル名 |
| Identifiers | CVE識別子などの分類情報 |
2.6.3. 優先順位付けの戦略
脆弱性への対応優先度を決定する際の推奨順序:
- KEV(Known Exploited Vulnerability)がある: 最優先で対応
- EPSS > 0.5 かつ Severity = Critical/High: 高優先度
- Reachable = true: 実際に使用されている脆弱性
- CVSS score > 7.0: 重大度が高い
- その他: 計画的に対応
2.7. 出力成果物
2.7.1. 依存関係スキャンレポート
ファイル名: gl-dependency-scanning-report.json
内容: すべての脆弱性の詳細を含むJSON形式のレポート
用途:
- GitLab UIでの表示
- 外部ツールとの連携
- 監査証跡
2.7.2. CycloneDX Software Bill of Materials (SBOM)
ファイル名形式: gl-sbom-<package-type>-<package-manager>.cdx.json
生成場所: 検出されたロックファイルまたはビルドファイルと同じディレクトリ
例: 以下のようなプロジェクト構造の場合:
.
├── ruby-project/
│ └── Gemfile.lock
├── php-project/
│ └── composer.lock
└── go-project/
└── go.sum
以下のSBOMが生成されます:
.
├── ruby-project/
│ ├── Gemfile.lock
│ └── gl-sbom-gem-bundler.cdx.json
├── php-project/
│ ├── composer.lock
│ └── gl-sbom-packagist-composer.cdx.json
└── go-project/
├── go.sum
└── gl-sbom-go-go.cdx.json
2.7.3. 複数のSBOMをマージする
複数のSBOMを1つにまとめる場合:
stages:
- test
- merge-cyclonedx-sboms
include:
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
merge cyclonedx sboms:
stage: merge-cyclonedx-sboms
image:
name: cyclonedx/cyclonedx-cli:0.25.1
entrypoint: [""]
script:
- find . -name "gl-sbom-*.cdx.json" -exec cyclonedx merge --output-file gl-sbom-all.cdx.json --input-files "{}" +
# オプション: マージされたSBOMを検証
- cyclonedx validate --input-version v1_4 --input-file gl-sbom-all.cdx.json
artifacts:
paths:
- gl-sbom-all.cdx.json
2.8. カスタマイズオプション
2.8.1. グローバル設定
| CI/CD変数 | デフォルト値 | 説明 |
|---|---|---|
DS_EXCLUDED_PATHS |
"spec, test, tests, tmp" |
スキャンから除外するパス(カンマ区切り) |
DS_MAX_DEPTH |
2 |
スキャンするディレクトリの深さ(-1で無制限) |
DS_EXCLUDED_ANALYZERS |
- | 除外するアナライザー名(カンマ区切り) |
SECURE_ANALYZERS_PREFIX |
registry.gitlab.com/security-products/analyzers |
Dockerレジストリのプレフィックス |
使用例:
variables:
DS_EXCLUDED_PATHS: "spec, test, tests, tmp, vendor"
DS_MAX_DEPTH: 3
2.8.2. アナライザー固有の設定
開発依存関係の制御:
variables:
DS_INCLUDE_DEV_DEPENDENCIES: "false" # 開発依存関係を除外
対応プロジェクト: Composer, Maven, npm, pnpm, Pipenv, Poetry
Java関連の設定:
variables:
DS_JAVA_VERSION: "17" # 利用可能: 8, 11, 17, 21
MAVEN_CLI_OPTS: "-DskipTests --batch-mode"
GRADLE_CLI_OPTS: "--no-daemon"
Python関連の設定:
variables:
PIP_INDEX_URL: "https://pypi.org/simple"
PIP_EXTRA_INDEX_URL: "https://private.pypi.example.com/simple"
PIP_REQUIREMENTS_FILE: "requirements-prod.txt" # 特定のファイルのみスキャン
Go関連の設定:
variables:
GOOS: "linux"
GOARCH: "amd64"
GOPRIVATE: "gitlab.example.com/*" # プライベートモジュール
2.8.3. 特定のアナライザーを除外
variables:
DS_EXCLUDED_ANALYZERS: "gemnasium-python"
2.9. プライベートリポジトリの認証
2.9.1. Maven プライベートリポジトリ
ステップ1: CI/CD変数を設定
プロジェクト設定 > CI/CD > Variables で以下を追加:
| Type | Key | Value | Protected | Masked |
|---|---|---|---|---|
| Variable | MAVEN_CLI_OPTS |
--settings mysettings.xml -Drepository.password=${MAVEN_PASSWORD} -Drepository.user=${MAVEN_USER} |
✓ | ✗ |
| Variable | MAVEN_USER |
yamada_taro |
✓ | ✗ |
| Variable | MAVEN_PASSWORD |
verysecret |
✓ | ✓ |
ステップ2: Maven設定ファイルを作成
リポジトリにmysettings.xmlを追加:
<settings>
<servers>
<server>
<id>private_server</id>
<username>${repository.user}</username>
<password>${repository.password}</password>
</server>
</servers>
</settings>
2.9.2. Python プライベートリポジトリ
pip の場合:
variables:
PIP_INDEX_URL: "https://private.pypi.example.com/simple"
Pipenv の場合:
variables:
PIPENV_PYPI_MIRROR: "https://private.pypi.example.com/simple"
セキュリティ上の注意: PIP_EXTRA_INDEX_URLを使用する場合、CVE-2018-20225の脆弱性に注意してください。攻撃者が公開PyPIに同名パッケージを配置し、より高いバージョン番号を付けることで、意図しないパッケージがインストールされる可能性があります。
2.9.3. npm プライベートリポジトリ
.npmrcファイルをリポジトリに追加:
registry=https://private.npm.example.com/
//private.npm.example.com/:_authToken=${NPM_TOKEN}
CI/CD変数にNPM_TOKENを設定:
| Type | Key | Value | Protected | Masked |
|---|---|---|---|---|
| Variable | NPM_TOKEN |
npm_xxxxxxxxxxxx |
✓ | ✓ |
2.10. カスタムTLS証明書の使用
自己署名証明書を使用するプライベートリポジトリの場合:
variables:
ADDITIONAL_CA_CERT_BUNDLE: |
-----BEGIN CERTIFICATE-----
MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB
...
jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs=
-----END CERTIFICATE-----
対応アナライザー:
- gemnasium (v2.8.0以降)
- gemnasium-maven (v2.9.0以降)
- gemnasium-python (v2.7.0以降)
2.11. オフライン環境での実行
2.11.1. 必要な準備
- アナライザーイメージのローカルコピー
以下のイメージをローカルDockerレジストリにインポート:
registry.gitlab.com/security-products/gemnasium:6
registry.gitlab.com/security-products/gemnasium:6-fips
registry.gitlab.com/security-products/gemnasium-maven:6
registry.gitlab.com/security-products/gemnasium-maven:6-fips
registry.gitlab.com/security-products/gemnasium-python:6
registry.gitlab.com/security-products/gemnasium-python:6-fips
-
GitLab advisory databaseのローカルコピー
-
Package Metadata Databaseへのアクセス
2.11.2. 設定例
方法1: GitLab advisory databaseのクローンを使用(推奨)
include:
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
variables:
SECURE_ANALYZERS_PREFIX: "docker-registry.example.com/analyzers"
GEMNASIUM_DB_REMOTE_URL: "https://gitlab.example.com/security/gemnasium-db.git"
方法2: GitLab advisory databaseのアーカイブを使用
include:
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
variables:
SECURE_ANALYZERS_PREFIX: "docker-registry.example.com/analyzers"
GEMNASIUM_DB_LOCAL_PATH: "./gemnasium-db-local"
GEMNASIUM_DB_UPDATE_DISABLED: "true"
dependency_scanning:
before_script:
- wget https://local.example.com/gemnasium_db.tar.gz
- mkdir -p $GEMNASIUM_DB_LOCAL_PATH
- tar -xzvf gemnasium_db.tar.gz --strip-components=1 -C $GEMNASIUM_DB_LOCAL_PATH
2.12. プロキシ環境での実行
2.12.1. Gradleプロジェクト
GradleラッパースクリプトはHTTP(S)_PROXY環境変数を読み取らないため、以下のように設定します:
variables:
GRADLE_CLI_OPTS: "-Dhttps.proxyHost=squid-proxy -Dhttps.proxyPort=3128 -Dhttp.proxyHost=squid-proxy -Dhttp.proxyPort=3128 -Dhttp.nonProxyHosts=localhost"
2.12.2. Mavenプロジェクト
MavenもHTTP(S)_PROXY環境変数を読み取らないため、settings.xmlで設定します:
settings.xml:
<settings>
<proxies>
<proxy>
<id>example-proxy</id>
<active>true</active>
<protocol>http</protocol>
<host>squid-proxy</host>
<port>3128</port>
<nonProxyHosts>localhost|*.example.com</nonProxyHosts>
</proxy>
</proxies>
</settings>
.gitlab-ci.yml:
variables:
MAVEN_CLI_OPTS: "--settings mysettings.xml"
2.12.3. その他のプロジェクト
一般的なHTTPプロキシ設定:
variables:
HTTPS_PROXY: "https://squid-proxy:3128"
HTTP_PROXY: "http://squid-proxy:3128"
NO_PROXY: "localhost,127.0.0.1,.example.com"
2.13. 複数ファイルの処理
2.13.1. Python
GitLabは、以下の優先順位で最初に検出されたファイルのみを処理します:
-
requirements.txt,requirements.pip,requires.txt(pip) -
Pipfile,Pipfile.lock(Pipenv) -
poetry.lock(Poetry) -
setup.py(setuptools)
注意: ルートディレクトリから検索を開始し、サブディレクトリに進みます。ルートディレクトリのPoetryロックファイルは、サブディレクトリのPipenvファイルより優先されます。
回避策: 複数のPythonプロジェクトがある場合、各プロジェクトで個別にスキャンジョブを定義します:
include:
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
gemnasium-python-dependency_scanning-project1:
extends: gemnasium-python-dependency_scanning
variables:
DS_PIP_DEPENDENCY_PATH: "project1"
gemnasium-python-dependency_scanning-project2:
extends: gemnasium-python-dependency_scanning
variables:
DS_PIP_DEPENDENCY_PATH: "project2"
2.13.2. Java と Scala
GitLabは、以下の優先順位で最初に検出されたビルドファイルのみを処理します:
-
pom.xml(Maven) -
build.gradle,build.gradle.kts(Gradle) -
build.sbt(sbt)
マルチモジュールプロジェクトの対応:
- Mavenのマルチモジュールプロジェクト: 親POMで宣言されたサブモジュールも分析
- Gradleのマルチプロジェクトビルド: 親ビルドファイルで宣言されたサブプロジェクトも分析
- sbtのマルチプロジェクトビルド: 親ビルドファイルで宣言されたサブプロジェクトも分析
2.13.3. JavaScript
Gemnasiumアナライザー: 複数のロックファイルをサポート
Retire.jsアナライザー: ディレクトリツリーをアルファベット順に走査し、最初に検出されたロックファイルのみを分析
ベンダー化されたライブラリ: Gemnasiumアナライザーは、パッケージマネージャーで管理されていないJavaScriptライブラリ(ベンダー化されたライブラリ)の脆弱性も検出できます。
variables:
GEMNASIUM_LIBRARY_SCAN_ENABLED: "true" # デフォルトで有効
注意: この機能を使用するには、JavaScriptロックファイルがコミットに含まれている必要があります。
2.13.4. Go
複数のgo.modファイルをサポートします。各go.modファイルに対して、以下の処理を実行します:
- Minimal Version Selectionを使用してビルドリストを生成
- 失敗した場合、
go.modファイル内の依存関係を直接パース
前提条件: go.modファイルはgo mod tidyでクリーンアップされている必要があります。
2.13.5. PHP, C, C++, .NET, C#, Ruby
これらの言語のアナライザーは、複数のロックファイルをサポートします。
2.14. トラブルシューティング
2.14.1. よくある問題と解決策
問題1: Gradleプロジェクトで依存関係が解決できない
原因: reports.html.destinationまたはreports.html.outputLocationプロパティがオーバーライドされている
解決策: これらのプロパティをオーバーライドしないでください
問題2: Mavenプロジェクトでgemnasium-maven-pluginが見つからない
原因: 隔離されたネットワークで、中央リポジトリがプライベートレジストリにミラーされている場合、Mavenはローカルリポジトリを検索しない
解決策: settings.xmlに<pluginRepositories>セクションを追加:
<pluginRepositories>
<pluginRepository>
<id>local2</id>
<name>local repository</name>
<url>file:///root/.m2/repository/</url>
</pluginRepository>
</pluginRepositories>
問題3: バージョン番号のパースエラー
原因: 以下の場合、バージョンの比較ができません:
- バージョンが不明
- バージョンが無効
- バージョンがブランチ名(
dev-master,1.5.xなど) - 比較するバージョンが曖昧(
1.0.0-20241502と1.0.0-2など)
解決策: GitLabアナライザーは誤検出を避けるため、これらの依存関係をスキップします。ログメッセージを確認してください。
問題4: FIPSモードでの制限
制限事項:
- Gradleプロジェクトは非サポート
- Yarnプロジェクトの自動修復は非サポート
-
DS_REMEDIATEは自動的にfalseに設定
解決策: FIPSモードが必要ない場合は無効化してください。
2.14.2. パフォーマンスへの影響
スキャン時間の目安:
| プロジェクトサイズ | 依存関係数 | スキャン時間 |
|---|---|---|
| 小規模 | < 50 | 1-2分 |
| 中規模 | 50-200 | 2-5分 |
| 大規模 | 200-500 | 5-10分 |
| 超大規模 | > 500 | 10-20分 |
最適化のヒント:
- 除外パスを設定: テストやドキュメントディレクトリを除外
-
深さを制限:
DS_MAX_DEPTHを適切に設定 - 開発依存関係を除外: 本番環境で使用しない依存関係は除外
- 並列実行: 複数のプロジェクトがある場合、並列でスキャン
variables:
DS_EXCLUDED_PATHS: "spec, test, tests, tmp, docs, examples"
DS_MAX_DEPTH: 2
DS_INCLUDE_DEV_DEPENDENCIES: "false"
3. 組織全体への展開戦略
3.1. 段階的な導入ロードマップ
3.1.1. フェーズ1: パイロットプロジェクト(1-2週間)
目標: 1-2個の小規模プロジェクトで機能を検証
アクション:
- 重要度が中程度のプロジェクトを選択
- Secret DetectionとDependency Scanningを有効化
- 検出された問題を修正
- 誤検出パターンを記録
- チームからフィードバックを収集
成功指標:
- パイプラインが正常に実行される
- 検出された脆弱性の80%以上を修正
- 開発者からの肯定的なフィードバック
3.1.2. フェーズ2: グループ展開(2-4週間)
目標: 1つのグループ内のすべてのプロジェクトに展開
アクション:
- スキャン実行ポリシーを作成
- グループレベルで設定を適用
- 開発者向けトレーニングを実施
- 除外ルールを標準化
- 修復プロセスを確立
成功指標:
- グループ内の90%以上のプロジェクトでスキャンが実行される
- 平均修復時間が2週間以内
- パイプライン失敗率が10%未満
3.1.3. フェーズ3: 組織全体展開(1-3ヶ月)
目標: すべてのプロジェクトに展開
アクション:
- 組織レベルのポリシーを作成
- 継続的な脆弱性スキャンを有効化
- ダッシュボードとレポートを設定
- 定期的なレビュープロセスを確立
- セキュリティチャンピオンを各チームに配置
成功指標:
- 組織内の95%以上のプロジェクトでスキャンが実行される
- Critical/High脆弱性の平均修復時間が1週間以内
- 新規脆弱性の検出率が月次で減少
3.2. スキャン実行ポリシーの活用
3.2.1. 基本的なポリシー
すべてのマージリクエストでスキャンを実行:
name: "マージリクエストでのセキュリティスキャン"
description: "すべてのマージリクエストでSecret DetectionとDependency Scanningを実行"
enabled: true
rules:
- type: pipeline
branches:
- "*"
actions:
- scan: secret_detection
- scan: dependency_scanning
3.2.2. 条件付きポリシー
特定のブランチのみでスキャンを実行:
name: "本番ブランチでのセキュリティスキャン"
description: "mainとreleaseブランチでのみスキャンを実行"
enabled: true
rules:
- type: pipeline
branches:
- main
- master
- release/*
actions:
- scan: secret_detection
- scan: dependency_scanning
3.2.3. スケジュール実行ポリシー
定期的にスキャンを実行:
name: "週次セキュリティスキャン"
description: "毎週日曜日にすべてのプロジェクトをスキャン"
enabled: true
rules:
- type: schedule
cadence: "0 0 * * 0" # 毎週日曜日 00:00
actions:
- scan: secret_detection
- scan: dependency_scanning
3.3. 継続的な脆弱性スキャン
パイプライン外でも、新たに公開された脆弱性を検出できます。
有効化方法:
プロジェクト設定 > Security & Compliance > Continuous Vulnerability Scanning を有効化
動作:
- デフォルトブランチの依存関係を定期的にスキャン
- 新しい脆弱性が公開されると自動的に検出
- パイプラインを実行せずに脆弱性を発見
利点:
- 既存のコードに対する新しい脆弱性を即座に検出
- 開発活動がない期間でもセキュリティを維持
- プロアクティブなセキュリティ管理
3.4. メトリクスと効果測定
3.4.1. 追跡すべきメトリクス
検出メトリクス:
- 検出された脆弱性の総数
- 重大度別の脆弱性数(Critical, High, Medium, Low)
- 誤検出率
- スキャンカバレッジ(スキャンされたプロジェクトの割合)
修復メトリクス:
- 平均修復時間(MTTR: Mean Time To Remediate)
- 重大度別の修復時間
- 修復率(修正された脆弱性の割合)
- 再発率
プロセスメトリクス:
- パイプライン成功率
- スキャン実行時間
- ブロックされたプッシュ数(Secret Push Protection)
- 開発者の対応時間
3.4.2. ダッシュボードの構築
GitLab APIを使用して、カスタムダッシュボードを構築できます:
# 例: Pythonスクリプトで脆弱性データを取得
import requests
gitlab_url = "https://gitlab.example.com"
private_token = "your_token"
project_id = "123"
headers = {"PRIVATE-TOKEN": private_token}
response = requests.get(
f"{gitlab_url}/api/v4/projects/{project_id}/vulnerabilities",
headers=headers
)
vulnerabilities = response.json()
# 重大度別に集計
severity_count = {}
for vuln in vulnerabilities:
severity = vuln['severity']
severity_count[severity] = severity_count.get(severity, 0) + 1
print(severity_count)
3.5. チーム教育とベストプラクティス
3.5.1. 開発者向けトレーニング
トレーニング内容:
-
セキュリティの重要性
- 実際のインシデント事例
- ビジネスへの影響
- 個人の責任
-
Secret Detectionの使い方
- シークレットの適切な管理方法
- CI/CD変数の使用
- 検出された場合の対応手順
-
Dependency Scanningの使い方
- 脆弱性レポートの読み方
- 優先順位の付け方
- 依存関係の更新方法
-
ハンズオン演習
- 実際のプロジェクトでスキャンを実行
- 脆弱性を修正
- 誤検出を除外
3.5.2. セキュリティチャンピオンプログラム
各チームにセキュリティチャンピオンを配置:
役割:
- チーム内のセキュリティ質問に回答
- 脆弱性レポートのレビュー
- ベストプラクティスの共有
- 新しいセキュリティ機能の評価
サポート:
- 定期的なセキュリティチャンピオンミーティング
- 専用のSlackチャンネル
- 追加のトレーニングリソース
3.5.3. ドキュメントとナレッジベース
作成すべきドキュメント:
-
クイックスタートガイド
- 5分で始めるSecret Detection
- 5分で始めるDependency Scanning
-
トラブルシューティングガイド
- よくある問題と解決策
- エラーメッセージの解説
-
ベストプラクティス集
- 言語別の推奨設定
- 除外ルールの例
- 修復パターン
-
FAQ
- 誤検出への対処
- パフォーマンスの最適化
- プライベートリポジトリの設定
4. ベストプラクティス
4.1. Secret Detectionのベストプラクティス
4.1.1. 多層防御アプローチ
3つの検出レイヤーすべてを有効化します:
# .gitlab-ci.yml
include:
- template: Jobs/Secret-Detection.gitlab-ci.yml
# Secret Push Protectionは設定で有効化
# Client-side Secret Detectionは自動的に有効
4.1.2. シークレットの適切な管理
推奨される方法:
- CI/CD変数を使用:
deploy:
script:
- echo "Deploying with API key: $API_KEY"
variables:
API_KEY: $CI_API_KEY # プロジェクト設定で定義
-
外部シークレット管理ツールを使用:
- HashiCorp Vault
- AWS Secrets Manager
- Azure Key Vault
- Google Secret Manager
-
環境変数ファイルを
.gitignoreに追加:
.env
.env.local
.env.*.local
secrets.yml
config/secrets.yml
4.1.3. 検出されたシークレットへの対応
即座に実行すべきアクション:
- シークレットを無効化: 元のシークレットを即座に無効化
- 新しいシークレットを生成: 新しいシークレットを生成し、安全に保存
- 履歴から削除: Git履歴からシークレットを削除(BFGまたはgit-filter-repoを使用)
- 影響範囲を調査: シークレットが悪用されていないか確認
- 再発防止策を実施: Secret Push Protectionを有効化
Git履歴からの削除例:
# BFGを使用
bfg --replace-text passwords.txt my-repo.git
# git-filter-repoを使用
git filter-repo --path-glob '**/*.env' --invert-paths
4.1.4. 除外設定の適切な使用
誤検出を減らすための除外設定:
variables:
SECRET_DETECTION_EXCLUDED_PATHS: "tests/, docs/, *.md, examples/"
注意: 除外設定は慎重に使用してください。本当にシークレットが含まれないことを確認してから除外します。
4.2. Dependency Scanningのベストプラクティス
4.2.1. ロックファイルの管理
必ずロックファイルをコミット:
# npm
git add package-lock.json
# yarn
git add yarn.lock
# Bundler
git add Gemfile.lock
# Composer
git add composer.lock
# Poetry
git add poetry.lock
# Go
git add go.sum
理由:
- 依存関係のバージョンを固定
- 再現可能なビルド
- 正確な脆弱性検出
4.2.2. 開発依存関係の扱い
本番環境で使用しない依存関係は除外:
variables:
DS_INCLUDE_DEV_DEPENDENCIES: "false"
ただし、以下の場合は含める:
- ビルドツールの脆弱性も検出したい
- 開発環境のセキュリティも重要
- CI/CDパイプラインで使用される
4.2.3. マージリクエストパイプラインでの実行
デフォルトブランチにマージする前に検出:
include:
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
dependency_scanning:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
4.2.4. 脆弱性の優先順位付け
推奨される優先順位:
- 最優先: KEV(Known Exploited Vulnerability)がある
- 高優先: EPSS > 0.5 かつ Severity = Critical/High
- 中優先: Reachable = true(実際に使用されている)
- 低優先: CVSS score > 7.0
- 計画的対応: その他
対応時間の目安:
| 優先度 | 対応期限 |
|---|---|
| 最優先 | 24時間以内 |
| 高優先 | 1週間以内 |
| 中優先 | 2週間以内 |
| 低優先 | 1ヶ月以内 |
4.2.5. 定期的なアップデート
推奨される更新頻度:
- セキュリティパッチ: 即座に適用
- マイナーバージョン: 月次
- メジャーバージョン: 四半期ごと
自動更新ツールの活用:
- Dependabot(GitHubから移行した場合)
- Renovate Bot
- GitLab Dependency Scanning の自動修復機能
variables:
DS_REMEDIATE: "true" # 自動修復を有効化(FIPSモード以外)
DS_REMEDIATE_TIMEOUT: "5m" # タイムアウト設定
注意: 自動修復はFIPSモードでは利用できません。
4.2.6. 誤検出への対処
誤検出の確認:
- 脆弱性の詳細を確認
- 影響を受けるコードパスを調査
- 実際に悪用可能か検証
除外方法:
脆弱性レポートで個別に却下(Dismiss):
- 理由を選択: False positive, Used in tests, Not applicable
- コメントを追加して理由を記録
プロジェクト全体で除外:
variables:
DS_EXCLUDED_PATHS: "vendor/, node_modules/test-package/"
4.2.7. モノレポでの運用
複数のプロジェクトを含むモノレポの場合:
include:
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
# プロジェクトAのスキャン
dependency_scanning_project_a:
extends: .ds-analyzer
variables:
DS_EXCLUDED_PATHS: "project-b/, project-c/"
only:
changes:
- project-a/**/*
# プロジェクトBのスキャン
dependency_scanning_project_b:
extends: .ds-analyzer
variables:
DS_EXCLUDED_PATHS: "project-a/, project-c/"
only:
changes:
- project-b/**/*
4.3. 共通のベストプラクティス
4.3.1. パイプラインの最適化
並列実行:
stages:
- test
- security
include:
- template: Jobs/Secret-Detection.gitlab-ci.yml
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
# Secret DetectionとDependency Scanningを並列実行
secret_detection:
stage: security
dependency_scanning:
stage: security
キャッシュの活用:
dependency_scanning:
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .cache/
4.3.2. 定期的なレビュー
週次レビュー:
- 新しく検出された脆弱性を確認
- 修復状況を追跡
- 誤検出を除外
月次レビュー:
- メトリクスを分析
- プロセスを改善
- チームにフィードバック
四半期レビュー:
- 全体的なセキュリティ姿勢を評価
- 新しいツールや機能を検討
- トレーニングニーズを特定
4.3.3. インシデント対応プロセス
Critical/High脆弱性が検出された場合:
- 即座に通知: セキュリティチームと開発チームに通知
- 影響範囲を評価: どのシステムが影響を受けるか確認
- 緊急パッチを適用: 可能な限り早く修正
- 本番環境を確認: 既に悪用されていないか調査
- 事後レビュー: 再発防止策を検討
5. まとめ
GitLabのSecret DetectionとDependency Scanningは、開発ライフサイクル全体を通じてセキュリティリスクを低減する強力な機能です。
5.1. Secret Detectionの主要ポイント
- 3層の防御: プッシュ時、パイプライン実行時、クライアント側で機密情報を検出
- 早期発見: リポジトリに到達する前、または公開される前に検出
- 自動対応: 一部のシークレットは自動的に無効化
- 全プランで利用可能: Free, Premium, Ultimateすべてで利用可能
5.2. Dependency Scanningの主要ポイント
- 包括的なスキャン: 直接的および推移的な依存関係をすべて分析
- 幅広いサポート: 14の言語と20以上のパッケージマネージャーに対応
- 詳細な情報: CVSS、EPSS、KEVなどの指標で優先順位付け
- SBOM生成: CycloneDX形式のSoftware Bill of Materialsを自動生成
- Ultimateプランで利用可能: より高度なセキュリティ機能
5.3. 導入の利点
- セキュリティリスクの早期発見: 本番環境に到達する前に問題を検出
- 開発速度の維持: 既存のCI/CDワークフローにシームレスに統合
- コンプライアンス対応: セキュリティ監査やコンプライアンス要件に対応
- コスト削減: セキュリティインシデントの防止により、事後対応コストを削減
- 開発者の意識向上: セキュアなコーディングプラクティスの定着
5.4. 次のステップ
- パイロットプロジェクトで開始: 1-2個の小規模プロジェクトで検証
- チームをトレーニング: 開発者向けのトレーニングを実施
- 段階的に展開: グループ単位で徐々に展開
- メトリクスを追跡: 効果を測定し、継続的に改善
- 組織全体に展開: すべてのプロジェクトでセキュリティスキャンを標準化
GitLabのSecret DetectionとDependency Scanningを活用することで、セキュアな開発プラクティスを実現し、組織全体のセキュリティ姿勢を向上させることができます。最小限の設定で導入でき、開発速度を犠牲にすることなく、強固なセキュリティ基盤を構築できます。