implementing-devsecops-security-scanning について
CI/CD パイプラインに自動セキュリティ検査を追加するチーム向けのスキルです。シークレット検出、SAST、SCA、DAST の設定から、結果をまとめたセキュリティゲートと開発者へのフィードバックまで扱います。
主な機能
- 01Gitleaks によるシークレット検出
- 02Semgrep による静的解析
- 03Trivy による依存関係とコンテナのスキャン
- 04OWASP ZAP によるステージング環境の検査
- 05結果集約とセキュリティゲート
- 06コミット前の開発者チェック
活用シーン
- 01CI/CD へのセキュリティスキャン追加
- 02重大な検出結果によるマージ阻止
- 03ビルド用 SBOM の生成
- 04コードのプッシュ前のシークレット検出
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill implementing-devsecops-security-scanningインストール後、Claude Code で/implementing-devsecops-security-scanningを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSEreferences/api-reference.mdscripts/agent.py詳細
DevSecOps セキュリティスキャンの実装
使用する場面
- 新規または既存の CI/CD パイプラインに自動セキュリティスキャンを設定する場合
- コードが本番環境に到達する前に脆弱性を検出し、セキュリティを開発の早い段階に組み込む場合
- 自動セキュリティテストを義務付けるコンプライアンス要件(SOC 2、PCI-DSS、ISO 27001)を満たす場合
- SAST、DAST、SCA を組み合わせて、包括的なアプリケーションセキュリティ対策を実現する場合
- 重大または高深刻度の脆弱性を含むデプロイを阻止するセキュリティゲートを確立する場合
手動の侵入テストの代わりとして使用しないでください。 自動スキャンでは一般的な脆弱性のパターンを検出できますが、ビジネスロジックの欠陥や複雑な攻撃チェーンを対象とする、人間が行うセキュリティ評価の代わりにはなりません。
前提条件
- CI/CD プラットフォーム:GitHub Actions、GitLab CI、Jenkins、または Azure DevOps
- スキャンツールの実行に使用するコンテナランタイム(Docker)
- DAST スキャン用のステージング環境の URL(DAST では静的コードをテストできません)
- CI/CD ワークフローファイルを変更する権限があるリポジトリアクセス
- ツール固有の要件:
- Semgrep:オープンソースのルールセット(
p/security-audit、p/owasp-top-ten)は無料 - Trivy:無料、アカウント不要
- OWASP ZAP:無料、Docker イメージを利用可能
- Gitleaks:無料、アカウント不要
- Semgrep:オープンソースのルールセット(
ワークフロー
ステップ 1:Gitleaks でシークレット検出を追加する
漏えいした認証情報は最優先で対処すべき検出事項であるため、シークレット検出を最初に実行します。.github/workflows/security.yml に追加します。
name: DevSecOps Security Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
secrets-scan:
name: Secrets Detection (Gitleaks)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for scanning all commits
- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
カスタムルールと許可リストを設定するには、リポジトリのルートに .gitleaks.toml を設定します。
[extend]
useDefault = true
[allowlist]
description = "Global allowlist"
paths = [
'''\.gitleaks\.toml''',
'''test/fixtures/.*''',
'''docs/examples/.*'''
]
[[rules]]
id = "custom-internal-api-key"
description = "Internal API key pattern"
regex = '''INTERNAL_KEY_[A-Za-z0-9]{32}'''
tags = ["internal", "api-key"]
ステップ 2:Semgrep で SAST スキャンを追加する
Semgrep は静的コード解析を実行し、セキュリティの脆弱性、バグ、コードパターンを検出します。
sast-scan:
name: SAST (Semgrep)
runs-on: ubuntu-latest
container:
image: semgrep/semgrep
steps:
- uses: actions/checkout@v4
- name: Run Semgrep SAST scan
run: |
semgrep scan \
--config p/security-audit \
--config p/owasp-top-ten \
--config p/secrets \
--severity ERROR \
--error \
--json \
--output semgrep-results.json \
.
- name: Upload SAST results
if: always()
uses: actions/upload-artifact@v4
with:
name: semgrep-results
path: semgrep-results.json
カスタムルールを作成するには、.semgrep/custom-rules.yml を作成します。
rules:
- id: no-exec-user-input
patterns:
- pattern: exec($INPUT)
- pattern-not: exec("...")
message: >
User input passed to exec(). This is a command injection vulnerability.
severity: ERROR
languages: [python]
metadata:
cwe: "CWE-78: OS Command Injection"
owasp: "A03:2021 - Injection"
- id: no-raw-sql-queries
patterns:
- pattern: cursor.execute(f"...")
- pattern: cursor.execute("..." + ...)
message: >
SQL query built with string concatenation or f-strings. Use parameterized queries.
severity: ERROR
languages: [python]
metadata:
cwe: "CWE-89: SQL Injection"
owasp: "A03:2021 - Injection"
ステップ 3:Trivy で SCA スキャンを追加する
Trivy は依存関係、コンテナイメージ、IaC ファイルをスキャンし、SBOM を生成します。
sca-scan:
name: SCA & Container Scan (Trivy)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Trivy filesystem scan (dependencies)
uses: aquasecurity/[email protected]
with:
scan-type: 'fs'
scan-ref: '.'
severity: 'CRITICAL,HIGH'
exit-code: '1'
format: 'json'
output: 'trivy-fs-results.json'
- name: Run Trivy IaC scan (Terraform, CloudFormation)
uses: aquasecurity/[email protected]
with:
scan-type: 'config'
scan-ref: '.'
severity: 'CRITICAL,HIGH'
exit-code: '1'
format: 'json'
output: 'trivy-iac-results.json'
- name: Upload SCA results
if: always()
uses: actions/upload-artifact@v4
with:
name: trivy-results
path: trivy-*.json
container-scan:
name: Container Image Scan (Trivy)
runs-on: ubuntu-latest
needs: [sast-scan] # Build image only after SAST passes
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t app:${{ github.sha }} .
- name: Scan container image
uses: aquasecurity/[email protected]
with:
image-ref: 'app:${{ github.sha }}'
severity: 'CRITICAL,HIGH'
exit-code: '1'
format: 'json'
output: 'trivy-image-results.json'
- name: Generate SBOM
uses: aquasecurity/[email protected]
with:
image-ref: 'app:${{ github.sha }}'
format: 'cyclonedx'
output: 'sbom.json'
- name: Upload SBOM
uses: actions/upload-artifact@v4
with:
name: sbom
path: sbom.json
ステップ 4:OWASP ZAP で DAST スキャンを追加する
DAST はデプロイ済みのステージング環境を対象に実行します。SAST/SCA より時間がかかるため、非同期またはスケジュールに従って実行します。
dast-scan:
name: DAST (OWASP ZAP)
runs-on: ubuntu-latest
needs: [deploy-staging] # Must run after app is deployed to staging
steps:
- uses: actions/checkout@v4
- name: Run ZAP Baseline Scan (fast, suitable for CI)
uses: zaproxy/[email protected]
with:
target: ${{ vars.STAGING_URL }}
rules_file_name: '.zap/rules.tsv'
cmd_options: '-a -j'
# For nightly full scans, use action-full-scan instead:
# - name: Run ZAP Full Scan (comprehensive, 30-60 min)
# uses: zaproxy/[email protected]
# with:
# target: ${{ vars.STAGING_URL }}
アラートのしきい値を設定するには、.zap/rules.tsv を作成します。
10010 IGNORE (Cookie No HttpOnly Flag - acceptable for non-sensitive cookies)
10011 IGNORE (Cookie Without Secure Flag - staging uses HTTP)
90033 WARN (Loosely Scoped Cookie)
10038 FAIL (Content Security Policy Header Not Set)
40012 FAIL (Cross Site Scripting - Reflected)
40014 FAIL (Cross Site Scripting - Persistent)
40018 FAIL (SQL Injection)
90019 FAIL (Server Side Code Injection)
90020 FAIL (Remote OS Command Injection)
ステップ 5:結果を集約し、セキュリティゲートを適用する
すべてのスキャン結果を集約し、合格/不合格のゲートを適用するサマリージョブを作成します。
security-gate:
name: Security Gate
runs-on: ubuntu-latest
needs: [secrets-scan, sast-scan, sca-scan, container-scan]
if: always()
steps:
- name: Check scan results
run: |
echo "Checking security scan results..."
# Fail the pipeline if any upstream job failed
if [[ "${{ needs.secrets-scan.result }}" == "failure" ]]; then
echo "BLOCKED: Secrets detected in repository"
exit 1
fi
if [[ "${{ needs.sast-scan.result }}" == "failure" ]]; then
echo "BLOCKED: SAST found critical/high vulnerabilities"
exit 1
fi
if [[ "${{ needs.sca-scan.result }}" == "failure" ]]; then
echo "BLOCKED: SCA found critical/high vulnerable dependencies"
exit 1
fi
if [[ "${{ needs.container-scan.result }}" == "failure" ]]; then
echo "BLOCKED: Container image has critical/high vulnerabilities"
exit 1
fi
echo "All security gates passed"
ステップ 6:ブランチ保護ルールを設定する
セキュリティパイプラインを必須のステータスチェックとして適用します。
GitHub Repository > Settings > Branches > Branch Protection Rules
Branch name pattern: main
Require status checks to pass before merging: Enabled
Required status checks:
- Secrets Detection (Gitleaks)
- SAST (Semgrep)
- SCA & Container Scan (Trivy)
- Security Gate
Require branches to be up to date before merging: Enabled
ステップ 7:開発者へのフィードバックループを設定する
開発者がプッシュ前に問題を検出できるよう、pre-commit フックを設定します。
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.22.1
hooks:
- id: gitleaks
- repo: https://github.com/semgrep/semgrep
rev: v1.102.0
hooks:
- id: semgrep
args: ['--config', 'p/security-audit', '--config', 'p/owasp-top-ten', '--error']
pre-commit をインストールして有効化します。
pip install pre-commit
pre-commit install
pre-commit run --all-files # Test against existing codebase
主要な概念
| 用語 | 定義 |
|---|---|
| SAST(静的アプリケーションセキュリティテスト) | ソースコードを実行せずに解析してセキュリティの脆弱性を検出します。実行が速く、早期に問題を検出できますが、実行時の欠陥は検出できません |
| DAST(動的アプリケーションセキュリティテスト) | リクエストを送信してレスポンスを解析し、実行中のアプリケーションをテストします。実行時の問題を検出できますが、デプロイ済みの環境が必要です |
| SCA(ソフトウェア構成分析) | プロジェクトの依存関係を脆弱性データベース(NVD、GitHub Advisory)と照合し、既知の脆弱性があるライブラリを検出します |
| SBOM(ソフトウェア部品表) | アプリケーション内のすべてのコンポーネントと依存関係を機械可読形式で一覧にしたもので、脆弱性の追跡とコンプライアンスに使用します |
| シフトレフト | セキュリティテストを SDLC のより早い段階に移行し、デプロイ後ではなく、コミット前や CI の段階で実施するセキュリティ手法です |
| セキュリティゲート | セキュリティスキャンの結果が定義済みの深刻度しきい値を超えた場合に、デプロイを阻止する CI/CD パイプラインのチェックポイントです |
| pre-commit フック | コードのコミット前にセキュリティチェックを実行するローカルの Git フックで、開発者に最速でフィードバックを提供します |
検証
- Gitleaks が、ハードコードされたシークレットを含むコミットと PR をブロックする(ダミーの API キーでテストします)
- Semgrep のスキャンがすべての PR で実行され、検出結果がアノテーションまたはコメントとして報告される
- Trivy のファイルシステムスキャンが既知の脆弱性を持つ依存関係を検出する(脆弱なパッケージを追加してテストします)
- Trivy のコンテナースキャンが、ビルド済みの Docker イメージに対して正常に実行される
- SBOM が生成され、CycloneDX または SPDX 形式のビルド成果物として保存される
- OWASP ZAP のベースラインスキャンが、クラッシュせずにステージング URL に対して実行される
- いずれかのスキャンで重大または高深刻度の問題が検出された場合、セキュリティゲートのジョブが main へのマージをブロックする
- ブランチ保護ルールにより、マージ前に必須のステータスチェックが適用される
- プッシュ前に、プリコミットフックがローカルでシークレットと SAST の検出結果を捕捉する
- 開発者向けドキュメントで、スキャン結果の解釈方法と一般的な検出結果の修正方法が説明されている