

GitHound es un recopilador OpenGraph de BloodHound para GitHub, diseñado para mapear la estructura y los permisos de tu organización en un grafo navegable de rutas de ataque. Permite:
Modela entidades clave de GitHub
Visualiza y analiza en BloodHound
Con GitHound, obtienes un grafo claro e interactivo del panorama de permisos de GitHub, ideal para revisiones de seguridad, auditorías de cumplimiento e investigaciones rápidas de incidentes.
Para documentación detallada, consulta 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
Si la recopilación se interrumpe, reanúdala desde donde la dejaste:
Invoke-GitHound -Session $session -Resume
GitHound admite tanto sesiones con Personal Access Token como sesiones de instalación de GitHub App. El flujo de trabajo existente de GitHub App con ámbito de organización no cambia:
. ./githound.ps1
$session = New-GitHubJwtSession `
-OrganizationName "YourOrgName" `
-ClientId $clientId `
-PrivateKeyPath $privateKeyPath `
-InstallationId $installationId
Invoke-GitHound -Session $session -CollectAll
La misma función también puede crear sesiones compatibles con enterprise:
. ./githound.ps1
$session = New-GitHubJwtSession `
-EnterpriseName "YourEnterpriseSlug" `
-ClientId $clientId `
-PrivateKeyPath $privateKeyPath `
-InstallationId $installationId `
-PersonalAccessToken $pat
Las sesiones compatibles con enterprise conservan múltiples contextos de autenticación en el GitHound.Session devuelto:
Headers: las cabeceras de token de instalación de GitHub App que se usan para la recopilación normalJwtHeaders: las cabeceras JWT de GitHub App que se usan para endpoints a nivel de aplicación, como la enumeración de instalacionesPatHeaders: cabeceras opcionales de Personal Access Token para rutas de recopilación que requieren autenticación con token de usuarioPara enumerar las instalaciones que pertenecen a la GitHub App autenticada:
Get-GitHubAppInstallation -Session $session |
Select-Object TargetType, InstallationId, Login, Name, SuspendedAt
El análisis de flujos de trabajo ahora está integrado en Invoke-GitHound cuando se usa -CollectAll. El recopilador:
GH_Workflow sin procesar y contenidos de flujos de trabajoGH_WorkflowJob y GH_WorkflowStepGH_CanPwnRequest y GH_CanDispatchTogithound_<orgId>.jsonPara fines de reanudación/depuración, el punto de control intermedio del análisis de flujos de trabajo se escribe como githound_WorkflowAnalysis_<orgId>.json.
GitHound ahora incluye una base mínima de recopilación enterprise mediante Git-HoundEnterprise.
Ese recopilador actualmente crea:
GH_EnterpriseGH_Organization stub ligeros para las organizaciones miembroGH_Contains desde la empresa hacia sus organizacionesLa recopilación de usuarios enterprise mediante Git-HoundEnterpriseUser añade:
GH_UserGH_HasMember desde la empresa hacia esos usuariosLa recopilación SAML enterprise mediante Git-HoundEnterpriseSamlProvider añade:
GH_SamlIdentityProviderGH_ExternalIdentityGH_HasSamlIdentityProvider desde la empresa hacia el proveedorEsta ruta requiere una sesión respaldada por PAT porque GitHub expone el SAML enterprise a través de enterprise.ownerInfo.
La recopilación de equipos enterprise mediante Git-HoundEnterpriseTeam añade:
GH_EnterpriseTeamGH_AssignedTo desde los equipos enterprise hacia las organizaciones asignadasGH_MemberOf desde los equipos enterprise hacia los nodos GH_Team ent: visibles en la organización mediante coincidencia de propiedadesmembers de los equipos enterprise y aristas GH_HasRole desde los usuarios hacia esos rolesLa recopilación de roles enterprise mediante Git-HoundEnterpriseRole añade:
GH_EnterpriseRoleGH_Contains desde la empresa hacia esos rolesGH_HasRole desde los usuarios asignados directamente y los equipos enterpriseowners predeterminado poblado a partir de enterprise.ownerInfo.admins cuando hay datos de administradores enterprise respaldados por PAT disponiblesPor ahora, las cadenas de permisos enterprise sin procesar se conservan en el nodo GH_EnterpriseRole dentro de su propiedad permissions, en lugar de expandirse en aristas de permisos dedicadas.
La recopilación SCIM enterprise añade actualmente:
SCIM_UserSCIM_GroupSCIM_Provisioned desde SCIM_User hacia GH_ExternalIdentitySCIM_Provisioned desde SCIM_Group hacia GH_EnterpriseTeam cuando GitHub expone el group_id del equipo enterpriseSCIM_MemberOf desde SCIM_User hacia SCIM_GroupEsto le proporciona a GitHound un puente independiente del proveedor desde el esquema SCIM compartido hacia el modelo nativo de identidad y equipos enterprise de GitHub.
Cuando un GH_SamlIdentityProvider recopilado identifica el IdP de origen, GitHound también puede añadir aristas de correlación SCIM conscientes del proveedor dentro de la salida sidecar de SCIM:
Okta_User -> SCIM_User
Okta_User.id = SCIM_User.externalIdOkta_Group -> SCIM_Group
Okta_Group.name = SCIM_Group.externalIdOkta_Group.oktaDomain = GH_SamlIdentityProvider.foreign_environmentidGitHound mantiene la capa SCIM en su propia salida sidecar para que estas asignaciones sigan siendo visibles sin mezclar nodos nativos de SCIM en el grafo enterprise principal, nativo de GitHub:
githound_<entId>.json contiene datos enterprise nativos de GitHubgithound_scim_<entId>.json contiene nodos nativos de SCIM y aristas puente de SCIMgithound_saml_<entId>.json contiene datos SAML y de identidades externasgithound_hybrid_<entId>.json contiene aristas entre modelos, como SAML_Implements, SAML_HasAccount y GH_SyncedTogithound_saml_<entId>.json también contiene la topología SAML normalizada para el proveedor de servicios de GitHub, incluyendo SAML_TrustsIssuer y SAML_HasAssertionConsumerServiceEl modelo nativo de proveedor de identidad de GitHub permanece intacto en las salidas nativas de GitHub/SAML:
GH_ExternalIdentityGH_HasExternalIdentityGH_MapsToUserLa capa SAML normalizada en githound_hybrid_<entId>.json ahora coloca SAML_HasAccount directamente sobre GH_User, a la vez que deriva match_values de las propiedades orientadas a SAML del GH_ExternalIdentity vinculado, como saml_identity_name_id y saml_identity_username.
Los nodos GH_Organization stub emitidos por la recopilación enterprise están marcados intencionadamente como collected = false. Representan el descubrimiento estructural desde el contexto enterprise y están pensados para enriquecerse más adelante con la recopilación normal de organizaciones.
Para la orquestación enterprise-first, Invoke-GitHoundEnterprise recopilará los datos compatibles con ámbito enterprise, enumerará las instalaciones de las organizaciones relacionadas y, a continuación, ejecutará el flujo de trabajo existente de Invoke-GitHound para cada organización en su propio subdirectorio dentro de la ruta de punto de control elegida.
Ejemplo:
$session = New-GitHubJwtSession `
-EnterpriseName "your-enterprise-slug" `
-ClientId $clientId `
-PrivateKeyPath $privateKeyPath `
-InstallationId $enterpriseInstallationId `
-PersonalAccessToken $pat
Invoke-GitHoundEnterprise -Session $session -CheckpointPath "./output/your-enterprise" -CollectAll
Para pruebas solo enterprise sin enumerar las organizaciones relacionadas:
Invoke-GitHoundEnterprise -Session $session -CheckpointPath "./output/your-enterprise" -EnterpriseOnly

Para documentación detallada, consulta BloodHound Docs - GitHound Schema.
Categorías clave de aristas:
Patrón principal de ruta de ataque:
(:GH_User)-[:GH_HasRole|GH_MemberOf|GH_AddMember*1..]->(:GH_RepoRole)-[:GH_AdminTo|GH_CanPush]->(:GH_Repository)
Encuentra el identificador de objeto de tu usuario objetivo:
MATCH (n:GH_User)
RETURN n
PISTA: Selecciona Table Layout
https://github.com/user-attachments/assets/1ddfd075-2a15-4aa9-bad7-74c43e6c82d6
Reemplaza el valor <object_id> de la consulta siguiente con el identificador de objeto del usuario:
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

Obtén el identificador de objeto de tu repositorio objetivo:
MATCH (n:GH_Repository)
RETURN n
Toma el identificador de objeto de tu repositorio objetivo y reemplaza con él el valor <object_id> de la consulta siguiente:
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

Encuentra entidades de GitHub que pueden asumir identidades federadas de Azure (relaciones de confianza OIDC):
// 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
¡Agradecemos y valoramos tus contribuciones! Para que el proceso sea ágil y eficiente, sigue estos pasos:
Comenta tu idea
Haz un fork y crea una rama
Haz un fork de este repositorio en tu propia cuenta.
Crea una rama temática para tu trabajo:
git checkout -b feat/my-new-feature
Implementa y prueba
Sigue el estilo y los patrones existentes en el repositorio.
Añade o actualiza las pruebas/ejemplos necesarios para cubrir tus cambios.
Verifica que tu código funciona como se espera:
# e.g. dot-source the collector and run it, or load the model.json in BloodHound
Envía un Pull Request
Sube tu rama a tu fork:
git push origin feat/my-new-feature
Abre un Pull Request contra la rama main de este repositorio.
En la descripción de tu PR, incluye:
Revisión y fusión
¡Gracias por ayudar a mejorar esta extensión! 🎉
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.
Salvo que se indique lo contrario mediante un archivo LICENSE o un encabezado de licencia de nivel inferior, todos los archivos de este repositorio se publican bajo la licencia Apache-2.0. Puedes encontrar una copia completa de la licencia en el archivo LICENSE de nivel superior.
| Categoría | Aristas clave | Descripción |
|---|
| Contención | GH_Contains, GH_Owns | Jerarquía organizativa |
| Asignación de roles | GH_HasRole, GH_MemberOf, GH_HasBaseRole | Quién tiene qué roles |
| Permisos de repositorio | GH_AdminTo, GH_CanPush, GH_CanPull | Qué pueden hacer los roles |
| Protecciones de rama | GH_BypassPullRequestAllowances, GH_RestrictionsCanPush | Acceso a nivel de rama |
| Secretos | GH_HasSecret | Mapeo de acceso a secretos |
| Multi-nube | GH_CanAssumeIdentity, GH_SyncedTo | Rutas de ataque a Azure/AWS |