Publicリポジトリを検知して通知する仕組みを作ってみた
2026年3月末に発生したAnthropic社のAIコーディングツール「Claude Code」のソースコード流出事件、びっくりしましたね。弊社でも他人事とは思えず、GitHubとForgejoを定期的に見回ってPublicリポジトリを検知したらMattermostに通知してくれる番犬システムを作ってみました。
技術スタック
実装① GitHub パトロール
組織のリポジトリ一覧を取得するため、repo スコープを持ったPersonal Access Tokenを発行します。
作成したTokenを MONITOR_TOKEN、MattermostのWebhook URLを MATTERMOST_WEBHOOK_URL としてリポジトリのSecretsに保存します。
.github/workflows/patrol.yml を作成し、schedule(cron)でJST 9:00・18:00の定期実行を設定します。
gh repo list --public で公開リポジトリのみを取得します。結果が空でない場合のみMattermostへPOSTするスクリプトを記述します。
通知ロジックのコア:
# Publicリポジトリを最大1000件取得 PUBLIC_REPOS=$(gh repo list $ORG_NAME \ --public --limit 1000 \ --json name --jq '.[].name') if [ ! -z "$PUBLIC_REPOS" ]; then # 検知時のみMattermostへ通知 MESSAGE="### 【警告】: 公開リポジトリを検知しました\n\ **$ORG_NAME** 内で以下がPublic設定です。\n\n\ - ${PUBLIC_REPOS// /\\n- }" curl -X POST -H 'Content-Type: application/json' \ -d "{\"text\": \"$MESSAGE\", \"username\": \"GitHubパトロールボット\"}" \ $MM_URL else echo "公開リポジトリはありませんでした。" fi
GitHub側は gh repo list --public オプションで最初からPublicのみ取得できるためシンプル。--limit 1000 で大規模組織にも対応します。
実装② Forgejo パトロール (EC2)
AWS上の既存サーバーに forgejo-runner を導入します。
組織のリポジトリ一覧を取得するため、リポジトリ閲覧権限を持ったAccess Tokenを発行します。
作成したTokenを FORGEJO_TOKEN、MattermostのWebhook URLを MATTERMOST_WEBHOOK_URL としてリポジトリのSecretsに保存します。
.forgejo/workflows/patrol.yml を作成し、schedule(cron)でJST 9:00・18:00の定期実行を設定します。
/api/v1/repos/search APIでリポジトリ一覧を取得し、jqで対象オーナーのPublicリポジトリのみ抽出します。結果が空でない場合のみMattermostへPOSTするスクリプトを記述します。
通知ロジックのコア:
# Forgejo APIでリポジトリ一覧を取得し、jqで絞り込み SERVER_URL="${GITHUB_SERVER_URL}" OWNER="${GITHUB_REPOSITORY_OWNER}" PUBLIC_REPOS=$(curl -s \ -H "Authorization: token $FORGEJO_TOKEN" \ "$SERVER_URL/api/v1/repos/search?private=false" | \ jq -r ".data[] | select(.owner.login == \"$OWNER\") | .full_name") if [ ! -z "$PUBLIC_REPOS" ]; then MESSAGE="### 【警告】: 公開リポジトリを検知しました\n\ **$OWNER** 内で以下のリポジトリがPublic設定です。\n$PUBLIC_REPOS" curl -i -X POST -H 'Content-Type: application/json' \ -d "{\"text\": \"$MESSAGE\", \"username\": \"Forgejoパトロールボット\"}" \ $MATTERMOST_URL else echo "公開リポジトリはありませんでした。" fi
調査で分かったこと
構築を進める中で、Forgejoサーバー側の設定を確認していたところ、重要な事実が判明しました。
管理画面のDanger Zoneを確認したところ、「公開 (Public)」に変更するボタン自体が存在しませんでした。管理者レベルの設定で、世界への公開がシステム的にブロックされていることが確認できました。
「Internal(ログイン者のみ)」は意図的な運用のケースがあるため通知対象から除外し、万が一Publicが有効化された場合のみ反応するサイレント監視の形としました。この『仕様の裏付け』が取れたことで、監視の設計を「Internalは許容、Publicは異常」と明確に定義できました。

コメント