GitLab:SAST を用いたアプリケーションの脆弱性検知から承認・マージまでの実践フロー
はじめに
こんにちは、クラウドエースの岸本です。
今回は以下の内容を解説しようと思います。
- GitLab の SAST 機能を用いて Cursor で開発したアプリケーションの脆弱性を検出する方法
- 脆弱性が検知されてから、検知内容を確認し、承認してマージするまでの一連のフロー
1. 環境
- ソースコード管理: GitLab SaaS
- CI/CD 実行環境: GitLab がホストする SaaS Runner
- プログラミング言語: Python を使用した Web アプリケーション
2. GitLab SAST の設定
2-1. リポジトリの準備
はじめに、GitLab 上にリポジトリを用意します。
GitLab のプロジェクト作成画面で「Enable Static Application Security Testing (SAST)」にチェックを入れます。
GitLab が自動で SAST の設定を行ってくれる .gitlab-ci.yml
を作成してくれます。
【GitLab のプロジェクト作成画面】
【作成したプロジェクト】
作成された .gitlab-ci.yml
の内容は以下のようになります。
stages:
- test
sast:
stage: test
include:
- template: Security/SAST.gitlab-ci.yml
2-2. SAST の実行
テスト用のコードを用意します。
はじめに、main
ブランチから feature/test-sast
というブランチを作成します。
【ブランチの作成】
feature/test-sast
ブランチに Cursor で開発したアプリケーションを push します。
【アプリケーションのコード】
ソースコードを push すると、GitLab CI/CD が自動で SAST ジョブを実行します。
2-3. SAST の結果確認
パイプラインの結果を確認するために、GitLab の「Build
」、「Pipelines
」タブを押下します。
先ほど作成したブランチのパイプラインが実行されているので、「Status」列の「Passed
」を押下します。
【Pipeline の詳細画面】
Pipeline の詳細画面が表示されます。
「semgrep-sast」ジョブを押下し、ジョブの詳細を確認します。
【Job の詳細画面】
ジョブの詳細画面が表示されます。
ジョブのログが表示され、SAST の結果が確認できます。
画面右側の「Job Artifacts」タブをクリックすると、SAST の結果(gl-sast-report.json)をダウンロードできます。
【Job Artifacts タブ】
以下がダウンロードしたgl-sast-report.json
の結果の一部です。
"version": "15.1.4",
"vulnerabilities": [
{
"id": "ID",
"category": "sast",
"name": "Improper neutralization of special elements used in an OS Command ('OS Command Injection')",
"description": "Found `subprocess` function `check_output` with `shell=True`. This is dangerous because this call will\nspawn the command using a shell process. Doing so propagates current shell settings and\nvariables,\nwhich makes it much easier for a malicious actor to execute commands. Use `shell=False`\ninstead.\n",
"cve": "semgrep_id:bandit.B602:147:147",
"severity": "High",
"scanner": {
"id": "semgrep",
"name": "Semgrep"
},
"location": {
"file": "app.py",
"start_line": 56,
},
・・・
"severity": "High",
と表示されていることから、脆弱性が検出されたことがわかります。
SAST ジョブの主な役割は、アプリケーションのソースコードを解析し、脆弱性を検出することです。
今回脆弱性が検出されたからといって、SAST ジョブが失敗するわけではありません。
SAST ジョブが失敗するケースとして、.gitlab-ci.yml
の記述ミス(YAML の書き方ミスなど)などがあります。
3. 脆弱性の承認プロセスの設定
3-1. 脆弱性が検出された場合の承認フロー
GitLab の SAST 機能を利用することで、脆弱性を検出することができました。
検出された脆弱性の軽度を確認し、適切な承認プロセスを経てからマージできるようにする仕組みを作成します。
今回は、Merge request approval policies を設定します。
Merge request approval policies を設定することで、特定の条件(今回のケースでは、SAST ジョブで脆弱性検出されたこと)でポリシーが発動し、承認可能なユーザーの承認が必要になります。
詳細はこちらから確認できます。
3-2. Merge request approval policies の設定
GitLab の「Secure」、「Policies」タブを押下し、Merge request approval policy
の「Select policy
」を押下します。
【Merge request approval policies の設定】
「Select policy
」を押下すると、ポリシーの選択画面が表示されます。
【ポリシーの設定画面】
ポリシーは細かく設定できます。例では以下のように設定してみます。
- デフォルトブランチで SAST セキュリティスキャンを実行し、クリティカル/高レベルの脆弱性を例外なく検出した場合にポリシーを発動
- 脆弱性解消後は、Aさん(セキュリティチーム)の承認が必須
【ポリシーの設定】
設定が完了したら、「Configure a merge request
」を押下します。
押下後、ポリシーを設定したプロジェクトと同階層にセキュリティポリシープロジェクトが自動作成され、そのプロジェクトのMerge request
画面に遷移します。
Merge
を押下すると、先ほど設定した Merge request approval policies の設定が完了します。
【Merge request の画面】
セキュリティポリシープロジェクトのリポジトリは以下のようになります。
【セキュリティポリシープロジェクトのリポジトリ】
これで、Merge request approval policies の設定が完了しました。
3-3. Merge request approval policies の動作確認
アプリケーションコードを管理しているプロジェクトに戻ります。
feature/test-sast
ブランチから main
ブランチに Merge request を作成します。
【Merge request の作成】
今回はテストのため、デフォルトの設定で作成します。
下記画像の赤枠部分の「Create merge request
」を押下します。
【Merge request の作成】
Merge requestの詳細画面が表示され、ポリシーが適用されていることがわかります。
【Merge request の詳細画面】
また、GitLab Security Bot が自動でコメントを追加してくれます。
今回の場合、app.py の 56 行目に脆弱性があることがわかります。
【GitLab Security Bot のコメント】
3-4. 脆弱性の確認と承認プロセス
GitLab Security Bot のコメントが脆弱性の指摘から、承認者(セキュリティチーム)は SAST で検出された脆弱性の内容と深刻度を確認します。
今回は例として、承認できる脆弱性であると判断し、承認を行います。
Merge request 画面の「Approve
」ボタンを押下することで行います。
【Approve の実行前】
【Approve の実行後】
承認後、プロダクトオーナーや責任者が内容を確認し、問題がなければマージを行います。
マージは、Merge request 画面の「Merge
」ボタンを押下することで行います。
【Merge の実行】
無事にマージが完了しました。
【マージ完了画面】
4. まとめ
今回は、GitLab の SAST 機能を利用して、Cursor で開発したアプリケーションの脆弱性を検出し、適切な承認プロセスを経てマージするまでの一連のフローを解説しました。
手軽に脆弱性を検出し、適切な承認プロセスを経て開発を進めることができるため、Cursor や Devin などローコード、ノーコードで開発したアプリケーションのセキュリティを担保しながら開発を進めることができると思います。
最後までお読みいただき、ありがとうございました。
Discussion