【セキュリティ自動化】GitHub Actionsで毎朝ライブラリの脆弱性を自動検知しSlackへ通知する設計術

【セキュリティ自動化】GitHub Actionsで毎朝ライブラリの脆弱性を自動検知しSlackへ通知する設計術

2026/08/05

「またパッケージの脆弱性報告が見過ごされていた……」

Webエンジニアとして複数のプロジェクトを抱えていると、依存ライブラリのセキュリティアップデート作業は後回しになりがちです。ある日突然、深刻な脆弱性 CVE が発表され、慌てて緊急対応に追われた経験を持つ方も少なくないでしょう。

今回は、GitHub ActionsのScheduled Trigger (cron) と pip-audit(または npm audit)を活用し、 「毎朝定時に依存パッケージの脆弱性を全自動スキャンし、問題があればSlackへピンポイント通知する仕組み」 の構築手順を余すことなく解説します。

なぜ「脆弱性スキャンの自動化」が必要なのか?

手動での脆弱性チェックは、どれほど意識の高いチームであっても必ず形骸化します。「リリース時に確認する」というルールを作っても、繁忙期には「今回は軽微な修正だから」とスルーされがちです。

私がこの自動化を導入するきっかけとなったのは、過去に古い依存ライブラリのセキュリティホールを突かれ、開発環境のトークンが漏洩しかけたヒヤリハットでした。それ以来、「人間の記憶や習慣に頼るセキュリティ運用は廃止する」と心に決めました。

自動スキャンフローの全体像

毎朝の始業前に自動実行され、脆弱性が検出された場合のみSlackへ通知を送る構成です。問題がない場合は通知を飛ばさない「サイレント運用」にすることで、通知のオオカミ少年化を防ぎます。

graph TD
    A["毎朝8:00 (GitHub Actions cron)"] --> B["リポジトリのチェックアウト"]
    B --> C["依存ライブラリのスキャン (pip-audit / npm audit)"]
    C --> D{"脆弱性は検出されたか?"}
    D -- "検出された" --> E["Slack Incoming Webhook へエラー詳細を送信"]
    D -- "問題なし" --> F["処理終了 (通知なし)"]
    E --> G["エンジニアが朝会で確認・対応"]

GitHub Actions ワークフローの実装コード

以下は、Pythonプロジェクトにおける pip-audit を用いた実際のワークフロー定義ファイル(.github/workflows/vulnerability-scan.yml)です。

name: Daily Security Vulnerability Audit

on:
  schedule:
    # 毎朝 UTC 23:00 (日本時間 8:00) に実行
    - cron: '0 23 * * *'
  workflow_dispatch: # 手動実行用ボタンも設置

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies & audit tool
        run: |
          python -m pip install --upgrade pip
          pip install pip-audit
          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

      - name: Run pip-audit
        id: audit
        continue-on-error: true
        run: |
          # 脆弱性レポートをファイルに出力
          pip-audit --desc on > audit_report.txt 2>&1
          echo "exit_code=$?" >> $GITHUB_OUTPUT

      - name: Notify Slack on failure
        if: steps.audit.outputs.exit_code != '0'
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
        run: |
          REPORT=$(cat audit_report.txt | head -n 30)
          PAYLOAD=$(jq -n --arg txt "⚠️ *【セキュリティ警告】依存ライブラリに脆弱性が検出されました* \n\`\`\`\n$REPORT\n\`\`\`" '{text: $txt}')
          curl -X POST -H 'Content-type: application/json' --data "$PAYLOAD" "$SLACK_WEBHOOK_URL"

実装のこだわりポイント

  1. continue-on-error: true とステータス制御 スキャンエラーでステップを即時異常終了させず、終了コードを取得して後続のSlack通知処理へ引き継いでいます。
  2. jq による安全なJSONペイロード生成 ログメッセージ内に特殊文字や改行が含まれていても、jq を経由することでSlackのAPIリクエストが壊れないように配慮しています。
  3. 通知の絞り込み head -n 30 でログの長さを制限し、Slackの通知画面が巨大なスタックトレースで埋め尽くされないように配慮しています。

実際に導入して得られた3つのメリット

  1. 脆弱性の即時手当がルーチン化された 毎朝Slackに通知が来ると、朝のコーヒーを飲みながら「このライブラリなら pip install --upgrade でバージョンアップすれば済むな」と、その日のタスクにサクッと組み込めるようになりました。
  2. 開発メンバーのセキュリティ意識向上 チーム全体で「ライブラリは常に最新近くに保つもの」という認識が共有され、バージョン固定の理由をコードレビューで確認する文化が定着しました。
  3. 無駄な「手作業チェック会議」の撲滅 月1回のセキュリティ点検会議が不要になり、月あたり約4時間のエンジニア工数が削減されました。

まとめ:セキュリティは「仕組み」で守る

セキュリティ対策で最も重要なのは、「エンジニアの善意や注意深さに依存しない環境づくり」です。

今回紹介したGitHub Actionsの設定は、15分もあればリポジトリに導入できます。まずは手元のプロジェクトで手動起動(workflow_dispatch)から試してみてください。

自動化によって守られた安心感のもとで、本来集中すべき機能開発に力を注いでいきましょう!