

GitHound は、GitHub 用の BloodHound OpenGraph コレクタであり、組織の構造と権限をナビゲート可能な攻撃経路グラフにマッピングするように設計されています。具体的には次のとおりです。
主要な GitHub エンティティをモデル化
BloodHound での可視化と分析
GitHound を使用すると、GitHub の権限環境の明確でインタラクティブなグラフが得られ、セキュリティレビュー、コンプライアンス監査、迅速なインシデント調査に最適です。
詳細なドキュメントについては、BloodHound Docs - GitHound を参照してください。
# 1. Load the collector
. ./githound.ps1
# 2. Create a session with your Personal Access Token
$session = New-GitHubSession -OrganizationName "YourOrgName" -Token (Get-Clipboard)
# 3. Run the collection
Invoke-GitHound -Session $session
# 4. Upload the resulting githound_<orgId>.json file to BloodHound
収集が中断された場合は、中断したところから再開できます:
Invoke-GitHound -Session $session -Resume
GitHound は、Personal Access Token セッションと GitHub App インストールセッションの両方をサポートしています。既存の組織スコープの GitHub App ワークフローは変更されません:
. ./githound.ps1
$session = New-GitHubJwtSession `
-OrganizationName "YourOrgName" `
-ClientId $clientId `
-PrivateKeyPath $privateKeyPath `
-InstallationId $installationId
Invoke-GitHound -Session $session -CollectAll
同じ関数を使用して、エンタープライズ対応セッションを作成することもできます:
. ./githound.ps1
$session = New-GitHubJwtSession `
-EnterpriseName "YourEnterpriseSlug" `
-ClientId $clientId `
-PrivateKeyPath $privateKeyPath `
-InstallationId $installationId `
-PersonalAccessToken $pat
エンタープライズ対応セッションは、返された GitHound.Session 上に複数の認証コンテキストを保持します:
Headers: 通常の収集に使用される GitHub App インストールトークンのヘッダーJwtHeaders: インストール列挙などのアプリレベルのエンドポイントに使用される GitHub App JWT ヘッダーPatHeaders: ユーザートークン認証が必要な収集パスのためのオプションの Personal Access Token ヘッダー認証された GitHub App に属するインストールを列挙するには:
Get-GitHubAppInstallation -Session $session |
Select-Object TargetType, InstallationId, Login, Name, SuspendedAt
ワークフローの解析は、-CollectAll を使用するときに Invoke-GitHound に組み込まれるようになりました。コレクタは次のことを行います:
GH_Workflow ノードとワークフローの内容を収集しますGH_WorkflowJob と GH_WorkflowStep に分析しますGH_CanPwnRequest と GH_CanDispatchTo を計算しますgithound_<orgId>.json 出力にマージします再開/デバッグの目的で、ワークフロー分析の中間チェックポイントは githound_WorkflowAnalysis_<orgId>.json として書き込まれます。
GitHound には、Git-HoundEnterprise による最小限のエンタープライズ収集基盤が含まれるようになりました。このコレクタは現在、以下を作成します:
GH_EnterpriseGH_Organization スタブノードGH_Contains エッジGit-HoundEnterpriseUser によるエンタープライズユーザー収集では、以下が追加されます:
GH_UserGH_HasMember エッジGit-HoundEnterpriseSamlProvider によるエンタープライズ SAML 収集では、以下が追加されます:
GH_SamlIdentityProviderGH_ExternalIdentityGH_HasSamlIdentityProviderこのパスには PAT バックのセッションが必要です。GitHub がエンタープライズ SAML を enterprise.ownerInfo を通じて公開するためです。
Git-HoundEnterpriseTeam によるエンタープライズチーム収集では、以下が追加されます:
GH_EnterpriseTeamGH_AssignedTo エッジent: GH_Team ノードへの GH_MemberOf エッジmembers ロールと、ユーザーからそれらのロールへの GH_HasRole エッジGit-HoundEnterpriseRole によるエンタープライズロール収集では、以下が追加されます:
GH_EnterpriseRoleGH_Contains エッジGH_HasRole エッジenterprise.ownerInfo.admins から入力されるデフォルトの owners ロール現時点では、生のエンタープライズ権限文字列は、専用の権限エッジに展開されるのではなく、GH_EnterpriseRole ノードの permissions プロパティに保持されます。
エンタープライズ SCIM 収集では現在、以下が追加されます:
SCIM_UserSCIM_GroupSCIM_User から GH_ExternalIdentity への SCIM_Provisionedgroup_id を公開する場合に、SCIM_Group から GH_EnterpriseTeam への SCIM_ProvisionedSCIM_User から SCIM_Group への SCIM_MemberOfこれにより、GitHound は共有 SCIM スキーマから GitHub のネイティブなエンタープライズ ID およびチームモデルへのプロバイダーに依存しないブリッジを提供します。
収集された GH_SamlIdentityProvider がアップストリーム IdP を識別する場合、GitHound は SCIM サイドカー出力内にプロバイダー対応の SCIM 相関エッジを追加することもできます:
Okta_User -> SCIM_User
Okta_User.id = SCIM_User.externalId によって一致Okta_Group -> SCIM_Group
Okta_Group.name = SCIM_Group.externalId によって一致Okta_Group.oktaDomain = GH_SamlIdentityProvider.foreign_environmentidGitHound は SCIM 層を独自のサイドカー出力に保持するため、SCIM ネイティブノードをメインの GitHub ネイティブエンタープライズグラフに混ぜることなく、これらのマッピングを可視化できます:
githound_<entId>.json にはエンタープライズの GitHub ネイティブデータが含まれますgithound_scim_<entId>.json には SCIM ネイティブノードと SCIM ブリッジエッジが含まれますgithound_saml_<entId>.json には SAML および外部 ID データが含まれますgithound_hybrid_<entId>.json には、SAML_Implements、SAML_HasAccount、GH_SyncedTo などのクロスモデルエッジが含まれますgithound_saml_<entId>.json には、SAML_TrustsIssuer と SAML_HasAssertionConsumerService を含む、GitHub サービスプロバイダーの正規化された SAML トポロジも含まれますネイティブの GitHub ID プロバイダーモデルは、GitHub/SAML ネイティブ出力でそのまま保持されます:
GH_ExternalIdentityGH_HasExternalIdentityGH_MapsToUsergithound_hybrid_<entId>.json の正規化された SAML 層は、SAML_HasAccount を GH_User に直接配置し、リンクされた GH_ExternalIdentity の SAML 向けプロパティ(saml_identity_name_id や saml_identity_username など)から match_values を導出します。
エンタープライズ収集によって出力される GH_Organization スタブは、意図的に collected = false とマークされています。これらはエンタープライズコンテキストからの構造的発見を表し、後で通常の組織収集によって拡張されることを意図しています。
エンタープライズファーストのオーケストレーションの場合、Invoke-GitHoundEnterprise はサポートされているエンタープライズスコープのデータを収集し、関連する組織のインストールを列挙してから、選択したチェックポイントパスの下の各組織の独自のサブディレクトリで既存の Invoke-GitHound ワークフローを実行します。
例:
$session = New-GitHubJwtSession `
-EnterpriseName "your-enterprise-slug" `
-ClientId $clientId `
-PrivateKeyPath $privateKeyPath `
-InstallationId $enterpriseInstallationId `
-PersonalAccessToken $pat
Invoke-GitHoundEnterprise -Session $session -CheckpointPath "./output/your-enterprise" -CollectAll
関連組織を列挙せずにエンタープライズのみをテストする場合:
Invoke-GitHoundEnterprise -Session $session -CheckpointPath "./output/your-enterprise" -EnterpriseOnly

詳細なドキュメントについては、BloodHound Docs - GitHound Schema を参照してください。
主要なエッジカテゴリ:
主な攻撃経路パターン:
(:GH_User)-[:GH_HasRole|GH_MemberOf|GH_AddMember*1..]->(:GH_RepoRole)-[:GH_AdminTo|GH_CanPush]->(:GH_Repository)
対象ユーザーのオブジェクト識別子を見つけます:
MATCH (n:GH_User)
RETURN n
ヒント: Table Layout を選択
https://github.com/user-attachments/assets/1ddfd075-2a15-4aa9-bad7-74c43e6c82d6
次のクエリの <object_id> の値をユーザーのオブジェクト識別子に置き換えます:
MATCH p = (:GH_User {objectid:"<object_id>"})-[:GH_MemberOf|GH_AddMember|GH_HasRole|GH_HasBaseRole|GH_Owns*1..]->(:GH_RepoRole)-[:GH_WriteRepoContents]->(:GH_Repository)
RETURN p

対象リポジトリのオブジェクト識別子を取得します:
MATCH (n:GH_Repository)
RETURN n
対象リポジトリのオブジェクト識別子を取得し、次のクエリの <object_id> の値をそれに置き換えます:
MATCH p = (:GH_User)-[:GH_MemberOf|GH_HasRole|GH_HasBaseRole|GH_Owns|GH_AddMember*1..]->(:GH_RepoRole)-[:GH_WriteRepoContents]->(:GH_Repository {objectid:"<object_id>"})
RETURN p

MATCH p = (:GH_User)-[:GH_HasRole|GH_HasBaseRole]->(:GH_OrgRole {short_name: "owners"})
RETURN p

MATCH p = (:AZUser)-[:GH_SyncedTo]->(:GH_User)
RETURN p

Azure フェデレーション ID(OIDC 信頼関係)を引き受けることができる GitHub エンティティを見つけます:
// All GitHub → Azure OIDC attack paths
MATCH p = (:GH_Repository|GH_Branch|GH_Environment)-[:GH_CanAssumeIdentity]->(:AZFederatedIdentityCredential)
RETURN p
// Users with paths to Azure via GitHub Actions
MATCH p = (:GH_User)-[:GH_HasRole|GH_MemberOf|GH_AddMember*1..]->(:GH_RepoRole)-[:GH_CanPush]->(:GH_Repository)-[:GH_CanAssumeIdentity]->(:AZFederatedIdentityCredential)
RETURN p
MATCH p = (:GH_Repository)-[:GH_HasSecret]->(:GH_OrgSecret)
RETURN p
MATCH p = (:GH_Repository)-[:GH_Contains]->(:GH_SecretScanningAlert)
RETURN p
コントリビューションを歓迎し、感謝します! プロセスをスムーズかつ効率的に進めるために、次の手順に従ってください:
アイデアを議論する
フォークしてブランチを作成する
このリポジトリを自分のアカウントにフォークします。
作業用のトピックブランチを作成します:
git checkout -b feat/my-new-feature
実装とテスト
リポジトリ内の既存のスタイルとパターンに従います。
変更をカバーするためにテスト/例を追加または更新します。
コードが期待どおりに実行されることを確認します:
# e.g. dot-source the collector and run it, or load the model.json in BloodHound
プルリクエストを送信する
ブランチをフォークにプッシュします:
git push origin feat/my-new-feature
このリポジトリの main ブランチに対してプルリクエストを開きます。
PR の説明には、以下を含めてください:
レビューとマージ
この拡張機能の改善にご協力いただきありがとうございます! 🎉
Copyright 2025 Jared Atkinson
Licensed under the Apache License, Version 2.0
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
下位レベルの LICENSE ファイルまたはライセンスヘッダーで特に注記されていない限り、このリポジトリ内のすべてのファイルは Apache-2.0 ライセンスの下で公開されています。ライセンスの完全なコピーは、最上位の LICENSE ファイルにあります。
| カテゴリ | 主要なエッジ | 説明 |
|---|
| 包含 | GH_Contains, GH_Owns | 組織階層 |
| ロール割り当て | GH_HasRole, GH_MemberOf, GH_HasBaseRole | 誰がどのロールを持っているか |
| リポジトリ権限 | GH_AdminTo, GH_CanPush, GH_CanPull | ロールが実行できる操作 |
| ブランチ保護 | GH_BypassPullRequestAllowances, GH_RestrictionsCanPush | ブランチレベルのアクセス |
| シークレット | GH_HasSecret | シークレットアクセスのマッピング |
| クロスクラウド | GH_CanAssumeIdentity, GH_SyncedTo | Azure/AWS への攻撃経路 |