README
¶
GitLabHound - GitLab OpenGraph Collector
GitLabHound is a BloodHound OpenGraph collector for GitLab to generate a navigable attack‑path graph composed of:
- Core GitLab resources: users, groups, roles, projects, repositories, branches, CI/CD pipelines and jobs
- Hybrid identities using SSO from Active Directory and Entra ID
- Cross-cloud paths through OIDC trust relationships
- Domain-joined Windows runners with shell executors
- Secrets leaked through public resources
- Renovate dependency bot abuse
Schema
Traversable edges are illustrated below, check the documentation for more specific information.
flowchart TD
GL_GroupVariable[fa:fa-sliders GL_GroupVariable]
AZUser[fa:fa-user AZUser]
AZServicePrincipal[fa:fa-robot AZServicePrincipal]
Computer[fa:fa-desktop Computer]
GL_ProjectVariable[fa:fa-sliders GL_ProjectVariable]
GL_PipelineSchedule[fa:fa-clock-rotate-left GL_PipelineSchedule]
GL_User[fa:fa-user GL_User]
GL_ProjectRole[fa:fa-user-tie GL_ProjectRole]
GL_GroupAccessToken[fa:fa-key GL_GroupAccessToken]
GL_Branch[fa:fa-code-branch GL_Branch]
GL_Variable[fa:fa-sliders GL_Variable]
GL_AccessToken[fa:fa-key GL_AccessToken]
GL_Instance[fa:fa-building GL_Instance]
GL_InstanceVariable[fa:fa-sliders GL_InstanceVariable]
GL_PipelineVariable[fa:fa-sliders GL_PipelineVariable]
User[fa:fa-user User]
GL_Group[fa:fa-user-group GL_Group]
GL_Project[fa:fa-diagram-project GL_Project]
GL_InstanceRole[fa:fa-user-tie GL_InstanceRole]
GL_ProjectAccessToken[fa:fa-key GL_ProjectAccessToken]
GL_LeakedSecret[fa:fa-key GL_LeakedSecret]
GL_JobLog[fa:fa-scroll GL_JobLog]
GL_JobArtifact[fa:fa-file-zipper GL_JobArtifact]
GL_PersonalAccessToken[fa:fa-key GL_PersonalAccessToken]
GL_GroupRole[fa:fa-user-tie GL_GroupRole]
GL_Group -->|GL_MemberOf| GL_Group
GL_GroupRole -->|GL_MemberOf| GL_Group
GL_Instance -->|GL_Defines| GL_InstanceVariable
GL_Group -->|GL_Defines| GL_GroupVariable
GL_Project -->|GL_Defines| GL_ProjectVariable
GL_PipelineSchedule -->|GL_Defines| GL_PipelineVariable
GL_User -->|GL_Owns| GL_PipelineSchedule
GL_User -->|GL_HasRole| GL_InstanceRole
GL_User -->|GL_HasRole| GL_GroupRole
GL_User -->|GL_HasRole| GL_ProjectRole
GL_GroupAccessToken -->|GL_HasRole| GL_GroupRole
GL_ProjectAccessToken -->|GL_HasRole| GL_ProjectRole
GL_GroupRole -->|GL_InheritRole| GL_GroupRole
GL_GroupRole -->|GL_InheritRole| GL_ProjectRole
GL_InstanceRole -->|GL_HasBaseRole| GL_InstanceRole
GL_InstanceRole -->|GL_HasBaseRole| GL_GroupRole
GL_InstanceRole -->|GL_HasBaseRole| GL_ProjectRole
GL_GroupRole -->|GL_HasBaseRole| GL_GroupRole
GL_ProjectRole -->|GL_HasBaseRole| GL_ProjectRole
GL_Group -->|GL_InvitedTo| GL_Group
GL_Group -->|GL_InvitedTo| GL_Project
GL_GroupRole -->|GL_ManageMembers| GL_Group
GL_ProjectRole -->|GL_ManageMembers| GL_Project
GL_ProjectRole -->|GL_CanPush| GL_Branch
GL_ProjectRole -->|GL_CanMerge| GL_Branch
GL_InstanceRole -->|GL_CanReadSecret| GL_LeakedSecret
GL_ProjectRole -->|GL_CanReadSecret| GL_LeakedSecret
GL_Variable -->|GL_ContainsCredentialsFor| GL_LeakedSecret
GL_JobLog -->|GL_ContainsCredentialsFor| GL_LeakedSecret
GL_JobArtifact -->|GL_ContainsCredentialsFor| GL_LeakedSecret
GL_InstanceVariable -->|GL_IsToken| GL_AccessToken
GL_GroupVariable -->|GL_IsToken| GL_AccessToken
GL_ProjectVariable -->|GL_IsToken| GL_AccessToken
GL_PipelineVariable -->|GL_IsToken| GL_AccessToken
GL_LeakedSecret -->|GL_IsToken| GL_AccessToken
GL_PersonalAccessToken -->|GL_HasPrivilegeOf| GL_User
GL_InstanceRole -->|GL_RenovateInviteAndTakeover| GL_User
AZUser -->|GL_SyncedTo| GL_User
User -->|GL_SyncedTo| GL_User
GL_Branch -->|GL_CanAssumeIdentity| AZServicePrincipal
GL_Branch -->|GL_BuildsAsSystem| Computer
[!note] The above diagram was generated with
gitlabhound visualize --traversable.
Nodes
Most important nodes, see the documentation for more specific information.
| Icon | Node Kind | Display Name |
|---|---|---|
| GL_Instance | GitLab instance metadata | |
| GL_User | User (or bot) account | |
| GL_Group | A collection of user and sub groups | |
| GL_Project | GitLab project with associated a repository, CI/CD pipelines, variables, ... | |
| GL_Repository | Git repository 1:1 relationship with project | |
| GL_Branch | Named branch associated with a repository | |
| GL_InstanceRole | Instance-wide permissions, administrator, member, external, unauthenticated | |
| GL_GroupRole | Group-level permissions, owner, maintainer, developer, ... | |
| GL_ProjectRole | Project-level permissions, owner, maintainer, developer, ... |
Edges
Most important edges, see the documentation for more specific information.
| Category | Key Edges | Description |
|---|---|---|
| Role Assignment | GL_HasRole, GL_MemberOf, GL_HasBaseRole, GL_InheritRole, GL_InvitedTo | Who holds which role on an instance, group, or project |
| Repository Access | GL_CanPush, GL_CanMerge, GL_CanPull, GL_ManageProtectedBranches | Branch-level read/write/merge rights |
| Privilege Management | GL_ManageMembers, GL_ManageVariables, GL_ManageRunners | Administrative control over resources |
| Secrets & Credentials | GL_IsToken, GL_HasToken, GL_ContainsCredentialsFor, GL_HasPrivilegeOf | Credential exposure via variables, artifacts, and access tokens |
| CI/CD Execution | GL_RunCICD, GL_Triggers, GL_CanUseRunner, GL_RunsOn | Pipeline trigger rights and runner assignment |
| Cross-Cloud & Hybrid | GL_CanAssumeIdentity, GL_SyncedTo, GL_HostedOn, GL_BuildsAsSystem | Attack paths to Azure, Entra ID, and domain-joined hosts |
| Privilege Escalation | GL_RenovateInviteAndTakeover | Lateral movement and account takeover techniques |
Usage Examples
An example dataset and a few saved queries can be used to explore the graph structure.

Example attack path starting in Entra ID, traversing GitLab and ending in Active Directory.
Collector Usage
Build the collector using:
go build
-
For hybrid-edges, ingest Active Directory (with ADIDNS information) and Entra ID data.
-
Create a Personal Access Token (PAT) by navigating to Edit profile > Access tokens and grant it the
read_apiscope. For best results, use an administrator account. -
Create a new BloodHound user with read-only permissions.
-
Configure credentials using environment variables:
export GITLAB_URL=https://git.pwn.gift/ export GITLAB_TOKEN=glpat-... export BLOODHOUND_USERNAME=api export BLOODHOUND_PASSWORD=... -
Register custom node kinds and associated icons in BloodHound:
gitlabhound register -
Collect data from your GitLab instance:
gitlabhound collect > gitlab.json -
Upload the resulting JSON file into BloodHound. Once ingested, perform post-processing to further enrich the graph:
gitlabhound enrich > gitlab-enrichment.json -
Upload the resulting JSON file into BloodHound.
[!note] It might be necessary to repeat the enrichment phase multiple times, in case post-processing edges depend on each other.
-
If you have findings from trufflehog or pipeleek in JSON form, you can try to map them to existing GitLab resources:
gitlabhound enrich secrets trufflehog.json pipeleek.json > gitlab-secrets.json
References
Documentation
¶
There is no documentation for this package.