ご注意) 本ブログ記事はワークショップ用です。後日一般化させる予定です。こちら が元になっています。
はじめに
セキュリティは、リリース直前に慌てて対応するものではありません。開発の初期段階からセキュリティチェックを組み込む「シフトレフト」の考え方は、今や現代的なソフトウェア開発において欠かせない要素になっています。
本記事では、GitLabのPipeline Execution Policyを使ってセキュリティスキャンをパイプラインに強制的に組み込む方法から、マージリクエスト(MR)での脆弱性確認、GitLab Duo AIによる脆弱性のトリアージと修正、さらに依存関係の可視化・SBOM(Software Bill of Materials)のエクスポート・ライセンスコンプライアンスまで、一連の流れをハンズオン形式で紹介します。
サンプルアプリケーションとして DAP Swag Shop というPython(Flask)製のアプリを題材にしています。
第1部: セキュリティポリシーの設定と動作を理解する
このセクションでは、GitLabの Pipeline Execution Policy を使って、セキュリティスキャンをパイプラインに強制的に組み込む方法を学びます。開発者がパイプラインを書き換えてもスキャンをスキップできない仕組みを作り、コードがコミットされた瞬間にセキュリティチェックが走る状態を実現します。
Step 0: 手順の準備
-
まず、プロジェクトのメインページを開いていることを確認してください。作業中はこの手順を別のタブまたは画面で開いておくことをお勧めします。
-
左側のナビゲーションメニューから Build > Pipeline editor を開きます。ブランチが
mainであることを確認してください(初期セットアップとしてmainブランチに直接コミットします)。既存の.gitlab-ci.ymlの内容を以下の内容で書き換え、Commit changes をクリックします。stages: - build build-job: stage: build script: - echo "Hello, GitLab CI/CD!"
Step 1: スキャナーのセットアップ
-
ページ上部のパンくずリストからグループ名をクリックし、New project をクリックして Create blank project を選択します。
-
プロジェクト名に
Swag Shop Scanner Pipelineと入力し、他の設定はそのままにして Create project をクリックします。 -
プロジェクトビューに移動したら、左側のナビゲーションから Build > Pipeline editor を開き、Configure pipeline をクリックします。
-
以下のコードをコピーして貼り付けます。GitLab CI/CD カタログの SAST CI/CD コンポーネントと標準のスキャンテンプレートを使用しています。
stages: - test include: # SASTコンポーネント: @mainより安定タグを使用することで予期しない破壊的変更を防ぐ - component: $CI_SERVER_FQDN/components/sast/sast@3.4.0 inputs: search_max_depth: "12" run_advanced_sast: true - template: Jobs/Dependency-Scanning.v2.gitlab-ci.yml - template: Jobs/Secret-Detection.gitlab-ci.yml # # 到達可能性機能を有効化する dependency-scanning: variables: DS_STATIC_REACHABILITY_ENABLED: "true" secret_detection: variables: # 過去の全コミットをスキャンする(初回導入時のシークレット漏洩を検出するため) # リポジトリが大きくなると実行時間が増加するため、初回スキャン後は見直しを検討 SECRET_DETECTION_HISTORIC_SCAN: "true"includeセクションを見ると、複数のセキュリティテンプレートと SAST コンポーネントがプロジェクトに取り込まれていることがわかります。これらはstagesに基づいて実行されるスキャンとジョブを定義します。テンプレートの詳細を確認するには Full configuration をクリックすると、すべてのテンプレートが展開された完全なパイプライン YAML が表示されます。また、左上のブランチアイコンをクリックし、さらに特定のテンプレートをクリックしてその定義を確認することもできます。 -
Edit タブをクリックして通常のエディターに戻ります。完了したら Commit changes をクリックし、ページ上部のパンくずリストを使ってグループビューに戻ります。
Step 2: パイプラインコンプライアンスの強制
-
DAP Swag Shopプロジェクトに戻ります。スキャナーパイプラインが定義できたので、DAP Swag Shop のパイプラインが実行されるたびに必ず実行されるよう、左側のナビゲーションから Secure > Policies を開きます。 -
New policy をクリックし、Pipeline execution policy を選択します。
-
名前と説明を入力し、Actions セクションまでスクロールします。Inject が選択されたままにして、Select projects をクリックしてスキャナープロジェクトを選択します。次に CI file の入力欄に
.gitlab-ci.ymlを追加します。 -
完了したら Create new project with the new policy をクリックし、表示されたページで Merge をクリックします。再びパンくずリストを使ってグループに戻り、
DAP Swag Shopをクリックします。
Step 3: 脆弱性レポートの確認と Advanced SAST の追跡
-
パイプラインが完了したら、左側のナビゲーションメニューから Secure > Vulnerability report を開きます。SAST、Dependency Scanning、Secret Detection によって多数の脆弱性が検出されていることを確認してください。SAST ではコマンドインジェクション(CWE-78)、SQL インジェクション(CWE-89)、パストラバーサル(CWE-22)など、Secret Detection では AWS 認証情報のハードコードなどが含まれます。
-
Vulnerability report で、SAST の OS Command Injection(CWE-78) の行をクリックして詳細ページを開きます。Code flow タブを開くと、
app.py内の 4 ステップが表示されます。フォーム入力(source)のrequest.form.get('customer_name', '')が、サニタイズされないままsubprocess.run()の引数(sink)に渡されるまでの経路が可視化されています。これが Advanced SAST によるテイント解析です。
Step 4: まとめ
このセクションでは、GitLab の Pipeline Execution Policy を使ってセキュリティスキャンをパイプラインに強制的に組み込む方法を学びました。スキャナー専用のプロジェクトを作成し、ポリシーで DAP Swag Shop に適用することで、開発者がパイプラインを書き換えてもスキャンをスキップできない仕組みを実現しました。また、Vulnerability report で実際の検出結果を確認し、Advanced SAST の Code flow によってユーザー入力から脆弱なコードまでの経路が可視化されることを体験しました。
第2部: マージリクエストのパイプライン実行結果を確認し、コードをマージしてセキュリティレポートを生成する
シフトレフトの流れに沿って、デプロイサイクルの各ステップにセキュリティ結果がどのように組み込まれているかを確認します。また、GitLab Duo AI が Swag Shop アプリケーションで検出された脆弱性を説明・トリアージし、AI による修正提案や Security Analyst Agent を活用して脆弱性に対処する方法を探っていきます。
Step 0: 事前準備
本来はコード変更を伴う MR でパイプラインを確認しますが、ここではパイプラインの動作を体験することが目的のため、README の更新という軽微な変更で MR を作成します。
-
左側のナビゲーションメニューから Plan > Issues を開き、New issue をクリックします。タイトルに
README を更新すると入力し、Create issue をクリックします。 -
作成した Issue のページで、右側の Create merge request をクリックします。ブランチ名は自動で生成されるのでそのままで構いません。Create merge request をクリックします。
-
マージリクエストのページで右上の Code をクリックし、Open in Web IDE を選択します。
README.mdを開き、任意の一行(例: 末尾に空行や短いコメント)を追加します。 -
左側のソースコントロールアイコンをクリックし、短いコミットメッセージを入力して Commit to... をクリックします。表示されたポップアップで Go to MR をクリックします。
-
MR でパイプラインが起動したことを確認してください。このMRを開いたまま、次の Step 1 に進みます。
Step 1: パイプラインのセキュリティタブで脆弱性を確認する
MR のパイプラインが完了したら、パイプライン詳細画面の Security タブで脆弱性一覧を直接確認できます。このタブは「このブランチに現在どれだけの脆弱性が存在するか」を把握するための参考情報として活用できます。新規・既存を問わずブランチ全体のスキャン結果が表示されるため、後述の MR セキュリティウィジェット(新規のみ表示)と使い分けることが重要です。
-
Step 0 で作成したマージリクエストを開き、Pipelines タブをクリックします。最新のパイプラインの行をクリックしてパイプライン詳細画面に移動します。
-
パイプライン詳細画面の上部にあるタブから Security をクリックします。このブランチのスキャンで検出された脆弱性が一覧表示されます。
-
Report Type フィルターを使って、SAST・Secret Detection・Dependency Scanning をそれぞれ選択し、スキャナーごとの検出結果を確認してみてください。
-
脆弱性の行をクリックして詳細を開きます。コード内のどこで問題が発生したか、なぜリスクなのかを確認できます。
Step 2: マージリクエストのセキュリティ結果
パイプラインの Security タブで全体像を把握したら、MR 画面に戻って開発者目線のセキュリティウィジェットを確認します。
-
Step 0 で作成したマージリクエストに戻ります。
-
承認セクションのすぐ下に Security scanning ウィジェットが表示されています。このウィジェットは、このブランチで新たに追加された脆弱性のみを表示します。
-
今回は脆弱性の検出結果が表示されていないはずです。これは、前のセクション(第1部)ですでに脆弱性を含むコードを main にマージ済みであるためです。MR のセキュリティウィジェットは「新規」の脆弱性だけを報告するため、main にすでに存在するものはここには表示されません。
-
これが MR セキュリティウィジェットの重要な特性です。開発者は自分のブランチで新たに持ち込んだ脆弱性だけに集中でき、既存の問題にノイズを埋もれさせることなくレビューできます。
-
次にスクロールダウンしてコードをマージします。MR がドラフト状態の場合は、まず Mark as ready をクリックしてドラフトを解除してから、リクエスト下部の Merge をクリックしてパイプラインを開始します。
-
マージ後、左側のナビゲーションメニューから Build > Pipelines をクリックし、最新のパイプラインをクリックします。
Step 3: 結果の解析
前のセクション(第1部)で Vulnerability Report はすでに確認しましたが、ここで改めて見てみましょう。main へのマージが完了したことで、レポートの内容が更新されているはずです。
-
main のパイプラインが完了したら、左側のナビゲーションメニューから Secure -> Vulnerability Report をクリックします。
-
SQL インジェクション (CWE-89) の脆弱性を探します。画面上部の Identifier フィルターをクリックし、
CWE-89と入力して絞り込みます。表示された脆弱性の行をクリックして詳細ページを開きます。
Step 4: GitLab Duo による脆弱性の説明
-
SQL インジェクションの脆弱性を開いた状態で、画面右上の AI Vulnerability Management ボタンをクリックし、Explain with AI を選択します。SQL インジェクションとは何か、Swag Shop アプリケーションがなぜ脆弱なのか、ユーザー入力から安全でないクエリまでのデータフローに関する具体的なコンテキストが回答として返ってきます。英語で回答が表示された場合は、続けて「日本語で」と入力してください。
-
次に、より強力な機能を試してみましょう。Resolve with AI ボタンをクリックします。GitLab Duo が脆弱性のコンテキストを分析し、コード修正を生成して直接提案します。
-
コード変更を行う前に特定の関数についてより多くのコンテキストが必要な場合は、Location(日本語版 UI では 影響を受ける場所)セクションのリンクされたファイルをクリックして、それぞれに表示されたファイルをみつけて、GitLab Duo Chatに尋ねるといった操作になります。
Step 5: Duo Security Analyst Agent
-
GitLab Duo Chat を開き、Security Analyst Agent を選択します。次のプロンプトを試してください:
このプロジェクトのクリティカルおよび高深刻度の脆弱性を一覧表示してくださいSQL インジェクションの脆弱性の EPSS スコアはいくつですか?コマンドインジェクションの脆弱性の修正を追跡するための Issue を作成してください
Step 6: まとめ
ワークショップのこのセクションが完了しました。
第3部: 依存関係リストの確認、SBOMのエクスポート、ライセンスコンプライアンスを学ぶ
依存関係の完全な可視化は、現代のソフトウェアサプライチェーンセキュリティの基盤です。このセクションでは、GitLabが自動生成するSBOM(Software Bill of Materials)を使って依存関係とライセンスを把握し、脆弱性の優先順位付けに役立てる方法を学びます。
Step 1: 依存関係リストとSBOMアーキテクチャ
-
左側のナビゲーションメニューから Secure > Dependency list をクリックし、アプリケーションに直接・間接的に含まれるすべての依存関係を確認します。
-
数ページをクリックして、アプリケーションに含まれるコンポーネントを確認してください。Swag ShopはFlask、Jinja2、Werkzeugをはじめ、多くのPythonパッケージを使用しており、それぞれが独自の依存ツリーを持っています。
-
依存関係リストには依存関係ごとに脆弱性の件数が表示されます。既知の脆弱性がある依存関係をクリックして、関連するCVEと深刻度を確認してください。
-
GitLab 18.2以降では、コンポーネント、バージョン、アクティビティ(セキュリティポリシーで利用可能) でフィルタリングすることもでき、古いバージョンや脆弱なバージョンを使用しているプロジェクトをすばやく特定できます。
Step 2: 到達可能性分析
-
依存関係スキャンに追加された最も強力な機能の一つが到達可能性分析です。この機能は、脆弱な依存関係がプロジェクトのコードから実際に_呼び出されているか_を特定し、本当に悪用可能な脆弱性の修正を優先できるようにします。
-
Secure > Vulnerability Report に移動し、Reachabilityフィルター(GitLab 18.2以降で利用可能)を探してください。到達可能性データが利用できる場合、Reachable(到達可能)な脆弱性のみを表示するようにフィルタリングできます。
-
脆弱性の総数と到達可能な脆弱性の数を比較してください。実際のプロジェクトでは、依存関係の脆弱性のうち実際に到達可能なものはごく一部であることが多く、セキュリティチームのトリアージ負担を大幅に軽減できます。
Step 3: SBOMレポートのダウンロードとライセンスコンプライアンス
-
Secure > Dependency list に移動します(Step 1で既に開いている場合はそのまま)。各依存関係の License 列に注目してください。MIT、BSD、Apache 2.0などの一般的なオープンソースライセンスや、GPLのバリアントが確認できます。多くの組織では、GPL-3.0やAGPLなどのコピーレフトライセンスが商用配布の要件と競合する場合があるため、ここで把握しておくことが重要です。
-
ページ右上の Export ボタンをクリックし、CycloneDX (JSON) としてエクスポート を選択します。JSON・CSV形式でのエクスポートも可能ですが、CycloneDX は業界標準の SBOM フォーマットです。
-
ダウンロードしたファイルを開いて構造を確認してください。各Pythonパッケージ(
flask、jinja2、werkzeug、sqlalchemyなど)のエントリに、バージョン・ライセンス・依存関係がまとめて記載されています。画面上で確認したライセンス情報がSBOMとして一つのファイルに集約されていることがわかります。
Step 4: まとめ
このセクションでは、依存関係リストの確認、到達可能性分析による優先順位付け、SBOMのエクスポート、ライセンスコンプライアンスの確認まで、GitLabのサプライチェーンセキュリティ機能を一通り体験しました。お疲れ様でした!
全体を振り返って
今回のハンズオンを通じて、以下の一連の流れを体験しました。
- Pipeline Execution Policy による、開発者が回避できないセキュリティスキャンの強制
- MRのSecurityタブとセキュリティウィジェットの違いを理解した、実践的なレビューフロー
- GitLab Duo AIによる脆弱性の説明・自動修正提案・Security Analyst Agentを使ったトリアージの効率化
- 依存関係リスト・到達可能性分析・SBOM・ライセンスコンプライアンスによるソフトウェアサプライチェーンの可視化
「セキュリティは後付けではなく、開発フローに組み込むもの」という思想を、GitLabの各機能がどのように実現しているかを体感できる内容になっていました。ぜひ皆さんの環境でも試してみてください。