Google Cloudを用いて、Dependabot alertsをSlackに即時通知させる

Sekine Hakurei

2026.3.27

はじめに

プロジェクトの依存関係に脆弱性が見つかった際、GitHubはDependabot alertsで知らせてくれます。しかし、GitHubの通知をメールやブラウザだけで追うのは限界があります。

「誰かが気づくだろう」「毎日欠かさずチェックしよう」といった人間の努力や意識に頼った運用は、いつか必ず破綻します。重大な脆弱性が見過ごされるリスクを低減するには、個人の頑張りではなく「仕組み」による解決が不可欠です。

この課題に対し、AWSを用いた連携手法は多くの技術ブログで紹介されていますが、Google Cloudを用いた実装例は意外にも多くありません。

そこで本記事では、Google CloudのCloud Run functions、GitHubのWebhook、SlackのIncoming Webhooksを組み合わせて、GitHubからSlackへ即時通知する方法を解説します。

システム構成

今回の仕組みの全体像は以下の通りで、非常にシンプルです。

  1. GitHubのDependabot alertsが脆弱な依存関係を検出し、アラートを作成します。
  2. GitHubのWebhookがアラートの作成を検知し、アラートに関するペイロードを含むHTTPリクエストをCloud Run functionsに送信します。
  3. Cloud Run functionsが受け取ったペイロードには、膨大な情報が含まれているため、通知に必要な項目のみを抽出します。そして、Slackの形式に合わせた送信用ペイロードを作成します。
  4. 作成した送信用ペイロードをCloud Run functionsからIncoming Webhooksに送信します。
  5. 送信されたペイロードをIncoming Webhooksが受け取り、設定されたチャンネルに投稿します。

実装ステップ

1. SlackのIncoming Webhookを作成する

まずは、Incoming Webhookを作成し、Slackチャンネルに通知したいメッセージとその他のオプションを含むJSONペイロードを送るための一意なURLを払い出します。

以下、具体的な手順です。

1. アプリ設定ページにアクセスし、「Create App」ボタンを押下する

2.次に「From Scratch」を選択し、アプリの名前とワークスペースを設定する

3.Incoming Webhooksの機能を有効化するために、左ペインの Features > Incoming Webhooksに遷移し、機能をONにする

4.「Add New Webhook」を押下し、Webhook 用のチャンネルを設定後、アクセスを許可する

5.作成完了

2. 通知内容の抽出・整形用のCloud Run functionsを作成する

次に、GitHubからのペイロードを受け取り、Slackへ届ける中継役となるサーバーレス関数(Cloud Run functions)を作成します。

今回はPythonを例に実装します。

関数のソースコード (main.py)

ペイロードから、脆弱性の重要度やサマリー、パッケージ名、詳細URLなどを抽出します。

import functions_framework
import requests
import os
import hmac
import hashlib


# Secret Managerで管理している値を、Cloud Run functionsの環境変数としてマウントして取得
SLACK_WEBHOOK_URL = os.environ.get('SLACK_WEBHOOK_URL')
GITHUB_WEBHOOK_SECRET = os.environ.get('GITHUB_WEBHOOK_SECRET')


def verify_github_signature(payload_body, signature_header):
    """GitHub Webhookの署名を検証"""
    if not GITHUB_WEBHOOK_SECRET:
        # Secretが設定されていない場合は検証をスキップ(開発環境など)
        return True
    
    if not signature_header:
        return False
    
    # GitHubは "sha256=<hash>" 形式で送信
    if not signature_header.startswith('sha256='):
        return False
    
    # 署名を計算
    expected_signature = hmac.new(
        GITHUB_WEBHOOK_SECRET.encode('utf-8'),
        payload_body.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    
    # タイミング攻撃を防ぐため、hmac.compare_digestを使用
    return hmac.compare_digest(f'sha256={expected_signature}', signature_header)

@functions_framework.http
def github_webhook_handler(request):
    # 1. POSTリクエスト以外を拒否
    if request.method != 'POST':
        return 'Method Not Allowed', 405

    # 2. GitHub Webhook署名の検証
    signature_header = request.headers.get('X-Hub-Signature-256')
    payload_body = request.get_data(as_text=True)
    
    if not verify_github_signature(payload_body, signature_header):
        return 'Unauthorized', 401

    payload = request.get_json(silent=True)
    if not payload:
        return 'Invalid JSON', 400

    # 3. Dependabot alerts以外のイベントを無視
    event = request.headers.get('X-GitHub-Event')
    if event != 'dependabot_alert':
        return 'Not a dependabot alert', 200

    action = payload.get('action')
    alert = payload.get('alert', {})

    # 4. アラート作成時のみ通知
    if action == 'created':
        severity = alert.get('security_advisory', {}).get('severity')
        summary = alert.get('security_advisory', {}).get('summary')
        package_name = alert.get('dependency', {}).get('package', {}).get('name')
        alert_url = alert.get('html_url')

        # Slack通知用のレイアウト構築
        slack_data = {
            "blocks": [
                {
                    "type": "section",
                    "text": {
                        "type": "mrkdwn",
                        "text": f"*Package:* `{package_name}`\n*Severity:* `{severity}`"
                    }
                },
                {
                    "type": "section",
                    "text": {
                        "type": "mrkdwn",
                        "text": f"*Summary:*\n<{alert_url}|{summary}>"
                    }
                }
            ]
        }

        # 5. Slackへ送信
        try:
            response = requests.post(
                SLACK_WEBHOOK_URL,
                json=slack_data,
                headers={'Content-Type': 'application/json'}
            )
            response.raise_for_status()
        except requests.exceptions.RequestException as e:
            print(f"Error sending to Slack: {e}")
            return 'Internal Server Error', 500

    return 'OK', 200

解説

簡単にコード内容を解説します。主要なポイントは以下の4点です。

  1. 署名の検証: verify_github_signature関数で、GitHubから送信されたリクエストが本物かどうかを、共有シークレット(GITHUB_WEBHOOK_SECRET)を用いて検証します。これにより、悪意のある第三者による偽造リクエストを防ぎます。なお、GITHUB_WEBHOOK_SECRETには、後述のGitHubのWebhook設定時に入力する任意のランダム文字列を環境変数として設定してください。
  2. フィルタリング: action == 'created'の条件を入れることで、アラートが閉じられた時などの不要な通知をカットし、作成時のみにフォーカスします。
  3. 通知内容の抽出: GitHubから届く膨大なペイロードの中から、severity(重要度)、summary(脆弱性の概要)、package_name(対象パッケージ)、html_url(詳細ページへのURL)など、対応の判断に必要な最小限の情報を抽出しています。
  4. 通知内容の整形: 抽出した情報を、Incoming Webhooksが受け取れるJSON形式のデータに変換します。また、単なるテキストではなく、SlackのBlock Kitを使用することで、パッケージ名や重要度を視覚的に見やすく整形しています。

3. GitHubのWebhookを設定する

最後に、アラートが作成された時に、先ほど作成したCloud Run functionsにアラートの内容を送信するように設定します。

以下、具体的な手順です。

  1. 通知対象のリポジトリを開き、Settings > Webhooks > Add webhook をクリックします。
  2. 各項目を以下のように設定します。
    • Payload URL: デプロイしたCloud Run functionsのURL
    • Content type: application/json
    • Secret: Cloud Run functionsの環境変数 GITHUB_WEBHOOK_SECRET に設定した文字列
    • SSL verification: Enable
  3. Which events would you like to trigger this webhook? で「Let me select individual events.」を選択します。
  4. イベント一覧から Dependabot alerts にチェックを入れます(他のチェックは外してOKです)。
  5. すぐにWebhookを有効にしたいので、Activeのチェックは入れたままとします。
  6. 最下部の Add webhook をクリックして完了です。

4. 動作確認

設定が完了すると、今後新しい脆弱性が検知されるたびに、Slackに以下のような通知が届くようになります。

おわりに

本記事では、Google Cloudを用いたDependabot alertsのSlack即時通知の方法について解説しました。

この仕組みを導入することで、人間の努力や意識に頼った負荷の高い運用から脱却し、脆弱性の検知から共有までを自動化することができました。

もちろん、通知を飛ばすだけでは根本的な解決にはなりません。この通知をトリガーに「誰が対応するか」「どのseverityまで対応するか」といった、チーム内のオペレーションフローをあわせて定義しておくことが、真に安全な開発環境を維持する鍵となります。

小さな自動化の積み重ねで、より開発に集中できる環境を作っていきましょう。

ブログ一覧へ戻る

お気軽にお問い合わせください

SREの設計・技術支援から、
SRE運用で使用する
ツールの導入など、
SRE全般についてご支援しています。

資料請求・お問い合わせ