gcp-cloudbuild-builds-create-as-legacy-sa

cloudbuild.builds.create gives the principal full control of build steps executed as the legacy Cloud Build service account, with no actAs requirement.

derived gcp emits CanModifyCode

match (effective permission)

{ "action": "cloudbuild.builds.create", "resource_type": "google.devtools.cloudbuild.v1.Build" }

where

no user-specified serviceAccount on the build (legacy SA is the default) legacy SA is PROJECT_NUMBER@cloudbuild.gserviceaccount.com

emit

source typeIdentity
target typeCompute
source<principal>
target<Cloud Build build node / BuildWorker>
permissionscloudbuild.builds.create
state logicACTIVE: cloudbuild.builds.create is a project-level permission; submitting a build with arbitrary steps is a single API call that runs immediately. No trigger, no actAs, no approval required unless an approval policy is active — in that case CONDITIONAL(build_approved). If a deny policy on cloudbuild.builds.create is in effect: BLOCKED.

Narrative

{principal.name} can submit a Cloud Build build (cloudbuild.builds.create) with arbitrary build steps; with no SA specified, the build executes as the legacy Cloud Build service account PROJECT_NUMBER@cloudbuild.gserviceaccount.com (historically roles/editor on the project). No actAs permission is required for the legacy SA path - a single API call yields code execution as that SA.

Raw rule rules/derived/gcp/cloudbuild.yaml

id: gcp-cloudbuild-builds-create-as-legacy-sa
emits: CanModifyCode
description: cloudbuild.builds.create gives the principal full control of build steps executed as the
  legacy Cloud Build service account, with no actAs requirement.
match_effective_permission:
  action: cloudbuild.builds.create
  resource_type: google.devtools.cloudbuild.v1.Build
where:
- no user-specified serviceAccount on the build (legacy SA is the default)
- legacy SA is PROJECT_NUMBER@cloudbuild.gserviceaccount.com
emit:
  source_type: Identity
  target_type: Compute
  source: <principal>
  target: <Cloud Build build node / BuildWorker>
  permissions:
  - cloudbuild.builds.create
  conditions: []
  state_logic: "ACTIVE: cloudbuild.builds.create is a project-level permission; submitting a build with\
    \ arbitrary steps is a single API call that runs immediately. No trigger, no actAs, no approval required\
    \ unless an approval policy is active \u2014 in that case CONDITIONAL(build_approved). If a deny policy\
    \ on cloudbuild.builds.create is in effect: BLOCKED."
  confidence: 0.97
  derived_from:
  - <cloudbuild.builds.create effective permission on principal>
  false_positive_note: "This path is ONLY valid for the legacy SA. Do NOT apply it when the build specifies\
    \ a user SA (that path requires iam.serviceAccounts.actAs \u2014 see gcp-cloudbuild-builds-create-with-sa).\
    \ If the project has removed the legacy SA or disabled it via org policy (iam.automaticIamGrantsForDefaultServiceAccounts),\
    \ the legacy SA may have no meaningful roles \u2014 resolve its actual effective roles before treating\
    \ this as a high-value escalation target. If a build approval policy is active, emit as CONDITIONAL(build_approved),\
    \ not ACTIVE."
  narrative: "{principal.name} can submit a Cloud Build build (cloudbuild.builds.create) with arbitrary\
    \ build steps; with no SA specified, the build executes as the legacy Cloud Build service account\
    \ PROJECT_NUMBER@cloudbuild.gserviceaccount.com (historically roles/editor on the project). No actAs\
    \ permission is required for the legacy SA path \u2014 a single API call yields code execution as\
    \ that SA."
move · open · esc close