2 min read

GCP CI/CD 01: Scanning GCP CI/CD's Private GitHub Repository — Writeup

GCP CI/CD 01: Scanning GCP CI/CD's Private GitHub Repository — Writeup
📚 Series · CyberWarFare Labs · CI/CD Security
  1. GitHub Enumeration 101 — full recon from a single PAT
  2. ▸ GCP CI/CD 01 — private repo to Cloud Run service name (this post)

Challenge Info

  • Platform: CyberWarFare Labs (CWL)
  • Category: CI/CD Security / GCP CI/CD
  • Difficulty: Easy (10 points)
  • Given: a GitHub Personal Access Token
  • Goal: find the name of the Cloud Run service used to deploy this repo's artifact

Walkthrough

The challenge hands you a GitHub PAT, and the way in is a private repo. What we're after isn't a static secret — it's the target of a deployment action: the Cloud Run service name, which lives in the repo's CI/CD config file.

Step 1: Identity and repo enumeration

TOKEN="[REDACTED_PAT]"

curl -s -H "Authorization: Bearer $TOKEN" https://api.github.com/user | grep '"login"'
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://api.github.com/user/repos?per_page=100&visibility=all" | grep -E '"full_name"|"private"'

The owner is Secure-Corp-Pro, and the token can reach the private repo Secure-Corp-Pro/GCP-CI-CD-01.

Step 2: Clone it and take stock of the structure

When you need to find one specific setting inside a whole repo, cloning it and searching locally is by far the fastest route:

git clone https://[email protected]/Secure-Corp-Pro/GCP-CI-CD-01.git
cd GCP-CI-CD-01
find . -path ./.git -prune -o -type f -print

There's no .github/workflows/ anywhere in the tree, but the repo root does have a cloudbuild.yaml — and that alone is intel: this pipeline runs on GCP-native Cloud Build, not GitHub Actions.

Step 3: Read the Cloud Build config

cat cloudbuild.yaml

The deploy step (Deploy container image to Cloud Run):

- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  entrypoint: gcloud
  args: ['run', 'deploy', '<SERVICE>', '--image', '$_DOCKER_URI/$_PROJECT_ID/$_ARTIFACT_REGISTRY_URI/$_DOCKER_IMAGE_NAME:latest', '--region', '$_DOCKER_REGION']

The first value right after gcloud run deploy is the Cloud Run service name (--image and --region are flags, not the name).

Flag (service name):

Redacted

Key Takeaways

  • "Deploying" is a CI/CD action, and the deployment target (cloud service name, project, region) lives in the repo's CI/CD config file — never in a data file. Going straight to the right file beats rummaging through the whole repo.
  • "No .github/workflows/ but there is a cloudbuild.yaml" is itself a finding: it tells you the pipeline runs on GCP Cloud Build. Both the presence and the flavour of a CI/CD config leak infrastructure details.
  • The first value after gcloud run deploy is the service name — don't confuse it with the --image / --region flags that follow.
  • cloudbuild.yaml usually leaks _PROJECT_ID, _ARTIFACT_REGISTRY_URI, _DOCKER_REGION and friends at the same time — exactly the foothold intel you'll need for later GCP levels, so jot them down while you're in there.
  • This level is fundamentally reconnaissance (mapping the cloud environment), not the final attack. You're drawing the map, not kicking in the door.

Handy Tricks

# Pull Cloud Run deployment-related lines out of the repo
grep -rniE "cloud run|run deploy|deploy-cloudrun|service:" \
  --include="*.yml" --include="*.yaml" .

# Cloud Build substitution variables start with $_ — the real values aren't in this file
# They usually hide in the Cloud Build trigger config, other files, or commit history
grep -rn '\$_' cloudbuild.yaml

Bonus: the "blueprint" this config file leaks

cloudbuild.yaml defines the full three-stage pipeline: build (docker packaging) → push (to Artifact Registry) → deploy (to Cloud Run), with the image path assembled from substitution variables like $_PROJECT_ID and $_ARTIFACT_REGISTRY_URI. So the shape of the pipeline is now known, but the actual values plugged into it haven't shown up yet — and that's precisely what GCP-CI-CD-02 goes digging for next.