Join our Newsletter — 33% off our NHI Course
Home› Guides› Google Cloud Build Security: Service Accounts, Approvals and…
Guide Software & AI Supply Chain

Google Cloud Build Security: Service Accounts, Approvals and Verifiable Provenance

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 8 November 2026 13 min read
On this page

Every Cloud Build run executes code from a repository with the permissions of a Google Cloud service account, so whoever can start or change a build can borrow that account's access. That is the root of most Cloud Build privilege escalation findings: a user with cloudbuild.builds.create, or a contributor who can open a pull request that triggers a build, ends up acting as an identity that can deploy, read secrets or push images. This guide explains how Cloud Build chooses its service account, which roles let people run builds as another identity, how triggers, approvals and private pools reduce exposure, how to use Secret Manager safely, and how to produce and verify SLSA provenance. It is for platform engineers, cloud security teams and auditors running Cloud Build in production. Google Cloud IAM fundamentals are covered in the Google Cloud IAM and Service Accounts Guide.

This is an independent guide from NHI Mgmt Group, based on Google Cloud's public documentation as of November 2026. It is not sponsored or reviewed by Google Cloud. Product features change, so confirm settings against Google Cloud's current documentation.

Key takeaways

  • The build service account is the blast radius. Builds run as a service account; choose a dedicated, narrowly scoped user-specified account per pipeline rather than a default account.
  • cloudbuild.builds.create is a privilege escalation path. Google states that Cloud Build Editor, Project Editor and Project Owner can run builds as the legacy service account, so access to submit builds equals access to that account's permissions.
  • Repository write access is build access. Anyone who can change the code or config being built changes what runs, even without project access; for GitHub pull request triggers, users with read access can submit a pull request that may execute a build.
  • Approvals gate sensitive triggers. A trigger marked as requiring approval holds builds as pending until a Cloud Build Approver approves or rejects them.
  • Provenance needs requestedVerifyOption VERIFIED. Cloud Build generates signed provenance at SLSA Build level 3 for artifacts pushed to Artifact Registry through the images field, which you can verify with slsa-verifier or Binary Authorization.

How identity and access work in Google Cloud Build

Cloud Build has two kinds of principals. Humans and automation call the Cloud Build API to create triggers, submit builds and approve them; IAM roles decide what they can do. Each build then runs as a service account, and every gcloud, Docker or API call in a build step uses that account's credentials. A third, Google-managed identity, the Cloud Build service agent, performs actions on behalf of the service, for example creating tokens when a build uses a service account from another project.

Which service account a build uses

AccountIdentifierWhen it is usedSecurity notes
Cloud Build legacy service account[email protected]Default in projects whose first build ran before the May and June 2024 change, unless org policy says otherwiseGoogle owned; holds roles/cloudbuild.builds.builder; cannot generate ID tokens; triggers use it by default where enabled
Compute Engine default service account[email protected]Default for builds submitted through the API or gcloud in projects created after the changeShared with Compute Engine workloads; older projects may have granted it the Editor role
User-specified service accountprojects/PROJECT_ID/serviceAccounts/SERVICE_ACCOUNTSet in the build config serviceAccount field or chosen on the triggerGoogle's recommended option; logs must go to a user-owned bucket or Cloud Logging

Three organisation policy constraints control the defaults: constraints/cloudbuild.disableCreateDefaultServiceAccount (enforced by default, disables the legacy account in new projects), constraints/cloudbuild.useBuildServiceAccount and constraints/cloudbuild.useComputeServiceAccount. Google also recommends keeping iam.automaticIamGrantsForDefaultServiceAccounts enabled, which stops Compute Engine and App Engine default accounts created on or after 3 May 2024 from receiving the Editor role. Review older projects, where the Compute Engine default account may still hold Editor and is now used for builds.

User-specified service accounts

  • Config file: set serviceAccount, then logging to CLOUD_LOGGING_ONLY, or GCS_ONLY with a logsBucket. Google-owned log buckets are not allowed, and a log bucket should not have a retention policy that blocks writes.
  • Triggers: choose the account on the trigger (console or --service-account). A serviceAccount in the build config is ignored for trigger-invoked builds, so review the trigger, not just the YAML.
  • Cross-project accounts: blocked while iam.disableCrossProjectServiceAccountUsage is enforced, which it is by default. Allowing it means disabling enforcement on the account's project and granting roles/iam.serviceAccountTokenCreator to the Cloud Build service agent of the building project, so treat it as an exception with an owner.
  • Service-to-service calls: the legacy account cannot generate ID tokens, so invoking Cloud Run or App Engine from a build needs a user-specified account.

Admin roles and privileged access

Map Cloud Build roles to duties and remember that roles which can create builds also confer the build account's power.

Role IDTitleWhat it allowsPrivilege note
roles/cloudbuild.builds.editorCloud Build EditorComplete control over Cloud Build resourcesCan run builds as the legacy account and change whether a trigger requires approval
roles/cloudbuild.builds.viewerCloud Build ViewerRead-only accessCan still read build logs, so keep secrets out of logs
roles/cloudbuild.builds.approverCloud Build ApproverApprove or reject pending buildsSeparate from editors to keep two-person control
roles/cloudbuild.connectionAdminCloud Build Connection AdminManage repository connectionsControls which source hosts feed builds
roles/cloudbuild.tokenAccessorCloud Build Token AccessorAccess read-only and read/write repository tokensRead/write source tokens allow code changes; prefer roles/cloudbuild.readTokenAccessor where writes are not needed
roles/cloudbuild.workerPoolOwner / workerPoolUserWorkerPool Owner / UserFull control of, or run builds in, private poolsPool owners change network reach
  • Escalation by submission: a principal with cloudbuild.builds.create and access to a powerful build account can do anything that account can do. Google names Cloud Build Editor, Project Editor and Project Owner as roles that let users run builds as the legacy account. Remove basic roles from developers and grant Cloud Build Editor only to pipeline administrators.
  • Escalation by trigger edit: UpdateBuildTrigger can switch the service account, the source branch or the approval flag. Alert on it.
  • Using the account: choosing a user-specified account for a build requires the iam.serviceAccounts.actAs permission on that service account. Grant it through roles/iam.serviceAccountUser on the specific account, not at project level. See the Top 10 GCP IAM Mistakes.

Integrations, API tokens and service accounts

Triggers and source connections

Triggers connect Cloud Build to source hosts such as GitHub, GitLab and Bitbucket through host connections whose tokens Cloud Build stores and exposes only to the token accessor roles. Controls that matter:

  • Pull request execution: Google warns that on GitHub pull request triggers any user with read access can open a pull request that may execute a build. Require approval (or the comment control options Google documents for GitHub App triggers) on pull request triggers, and never attach a privileged service account or deploy secrets to them. See the OWASP CI/CD Top 10 CICD-SEC-4 Poisoned Pipeline Execution Guide.
  • Approval required: tick Approval on the trigger (gcloud --require-approval). Builds wait as pending until approved with gcloud builds approve or rejected; pending builds older than two months cannot be acted on. Use a notifier filtered on PENDING so approvers see requests.
  • Allowed integrations: constraints/cloudbuild.allowedIntegrations limits which source hosts can interact with Cloud Build and overrides triggers and approvals.
  • Branch and file filters: included and ignored file globs decide what starts a build; they are a convenience, not a security boundary.

Secrets

Use Secret Manager through the availableSecrets block: each secretManager entry names a versionName and an env variable, steps list it in secretEnv, and commands reference it with a $$ prefix inside args. Grant roles/secretmanager.secretAccessor on each secret to the build's service account only. Google specifically advises against using the legacy service account here, because anyone who can run a trigger using that account gains the secret at build time. Never echo secrets in steps, since build logs are readable by Cloud Build Viewer. Background on the secret store is in the Secrets Management Guide.

Private pools

Private pools are dedicated workers in a Google-owned service producer network. Google documents that they can peer with your VPC to reach private resources, can be configured without public IPs and with or without public internet access, support VPC Service Controls, and offer up to 64 machine types. Use them when builds touch private artifact stores, databases or clusters, or when you need a perimeter around build egress. See the VPC Service Controls Guide.

Provenance and supply chain integrity

Set options.requestedVerifyOption to VERIFIED and push images through the images field to Artifact Registry; builds then succeed only if provenance is generated. Google states the provenance meets SLSA level 3 assurance. Provenance is produced for container images and for Go, Maven, Python and npm artifacts uploaded to Artifact Registry, and not when you push with an explicit docker push step. View it with gcloud artifacts docker images describe --show-provenance or in the Security insights panel, and verify with slsa-verifier v2.1 or later. The provenanceSigner signature is DSSE conformant and verifiable in Binary Authorization, which lets you block deployment of images that Cloud Build did not build from the expected source. See the SLSA and Build Provenance Guide and the Google Artifact Registry Security guide.

Logging and detection

Cloud Build writes Admin Activity audit logs for methods requiring ADMIN_WRITE permissions, filterable in Logs Explorer with protoPayload.serviceName="cloudbuild.googleapis.com". Route them with an organisation sink, as described in the Google Cloud Audit Logs and Log Sinks Guide.

EventAudit log methodWhat to look for
Build submittedCreateBuildManual builds by humans outside pipelines, builds naming an unexpected serviceAccount
Trigger created or changedCreateBuildTrigger, UpdateBuildTriggerService account swaps, approval removed, branch filters widened
Build approvedApproveBuildSelf-approval or approvals outside working hours
Secret accessedSecret Manager Data Access logs (if enabled)Access by build accounts not mapped to that secret
IAM change on build accountsSetIamPolicy on service accounts or projectsNew serviceAccountUser or tokenCreator grants

Metrics:

  • Share of triggers using a dedicated user-specified service account rather than a default account.
  • Number of principals holding cloudbuild.builds.create through Cloud Build Editor or basic roles.
  • Share of production deploy triggers requiring approval.
  • Share of production images with VERIFIED provenance enforced at deploy by Binary Authorization.
  • Pull request triggers with access to secrets or privileged accounts (target zero).

Responding to a suspected build account compromise

If a trigger, repository or build account is suspected of misuse, act in this order:

  1. Contain: disable the affected triggers and, if needed, the build service account itself; this stops new builds without deleting evidence.
  2. Scope: query CreateBuild and UpdateBuildTrigger entries for the period, list every build that ran as the account, and review their logs and the source revisions they built.
  3. Rotate: create new versions of every Secret Manager secret the account could access and revoke the old ones, and rotate repository connection tokens.
  4. Check outputs: identify images and artifacts pushed by suspect builds; images without valid provenance from the expected source should not be deployed.
  5. Recover: re-enable triggers with a new, narrower account and approval in place. The CI/CD Pipeline Compromise Playbook covers the wider response.

Hardening baseline

  1. Inventory: list triggers, their service accounts, connections, private pools and secrets referenced in availableSecrets across all projects.
  2. Set organisation policy: keep disableCreateDefaultServiceAccount and iam.automaticIamGrantsForDefaultServiceAccounts enforced, keep iam.disableCrossProjectServiceAccountUsage enforced except for documented exceptions, and set allowedIntegrations to approved source hosts.
  3. Create per-pipeline service accounts: one account per pipeline and environment, with only the roles that pipeline needs; move triggers one at a time, test in a non-production project, and roll back by reselecting the previous account on the trigger.
  4. Remove escalation paths: strip Project Editor and Owner from developers, restrict Cloud Build Editor, grant serviceAccountUser on individual accounts only.
  5. Gate production: require approval on deploy triggers and give Cloud Build Approver to a group separate from editors.
  6. Isolate pull request builds: separate triggers and accounts with no secrets or deploy rights for untrusted contributions.
  7. Move secrets to Secret Manager with per-secret accessor grants.
  8. Enable provenance and enforce it: VERIFIED on all image builds, Binary Authorization in audit mode first, then enforce.
  9. Use private pools for builds that reach private networks, with public IPs disabled where possible.

Small versus large estates: a small team can use one project, a handful of dedicated build accounts and manual approvals. Large estates should centralise build projects, use organisation policy to remove defaults everywhere, and enforce provenance at deploy time so a compromised project cannot ship unverified images.

Common misconfigurations

  • Default account with Editor: projects where builds run as the Compute Engine default service account that still holds roles/editor give every build project-wide write access.
  • Developers with Project Editor: basic roles include cloudbuild.builds.create, so developers can run builds as the build account and inherit its access.
  • Privileged pull request triggers: pull request builds that can read deploy secrets let an outside contributor run code that prints them. Secrets leak quickly once untrusted code runs in a pipeline, so keep deploy secrets out of pull request builds.
  • Secrets in substitutions or logs: putting tokens in substitution variables or echoing them exposes them to anyone with Cloud Build Viewer.
  • Provenance generated but never checked: enabling VERIFIED without Binary Authorization or slsa-verifier at deploy adds metadata but no control.
  • Trigger config trusted over trigger settings: reviewers approve a serviceAccount in YAML that the trigger ignores, while the trigger itself runs as a broader account.

Framework mapping

Cloud Build controlNIST SP 800-53 Rev 5NIST CSF 2.0Threat addressed
Dedicated least-privilege build accountsAC-6, AC-2PR.AA-05ATT&CK T1078.004 Cloud Accounts
Approvals and separate approversCM-3, AC-5PR.PS-01OWASP CICD-SEC-1 Insufficient Flow Control
Secret Manager with per-secret grantsIA-5, SC-28PR.AA-01ATT&CK T1552 Unsecured Credentials
Provenance and Binary AuthorizationSR-4, SI-7, SR-11PR.PS-01ATT&CK T1195.002 Compromise Software Supply Chain
Private pools and perimetersSC-7PR.PS-01Build egress and data exfiltration
Audit log routing and alertingAU-2, AU-6DE.CM-01OWASP CICD-SEC-10 Insufficient Logging

Practitioner checklist

  • Identify which default service account each project's builds use, and remove Editor from any default account that runs builds.
  • Assign a dedicated user-specified service account to every trigger, set on the trigger itself.
  • Remove basic roles from developers and limit Cloud Build Editor to pipeline administrators.
  • Grant roles/iam.serviceAccountUser per build account, never project-wide.
  • Require approval on production triggers and keep approvers separate from editors.
  • Run untrusted pull request builds with no secrets and no deploy permissions.
  • Deliver secrets through availableSecrets with per-secret Secret Accessor grants.
  • Set requestedVerifyOption VERIFIED and verify provenance at deploy with Binary Authorization.
  • Enforce allowedIntegrations and keep cross-project service account use disabled by default.
  • Alert on UpdateBuildTrigger, ApproveBuild and IAM changes to build accounts.

Standards and references

Related NHI Mgmt Group resources: Google Cloud IAM and Service Accounts Guide · CI/CD Pipeline Identity Security Guide · Google Cloud Organization Policy Guide · CI/CD Security Guide

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 8 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org