gcp-deploy-rollout-create-modifies-code
clouddeploy.rollouts.create (promotion) with actAs on the deploy SA triggers the deploy Cloud Build worker running as the deploy SA.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
?principal has effective clouddeploy.rollouts.create on the delivery pipeline
?deploy_sa is the deploy-phase execution SA for the target being promoted to
?deploy_sa is bound via
CanPassIdentity through iam.serviceAccounts.actAs (gcp-sa-act-as)
emit
| source type | Identity |
|---|---|
| target type | BuildWorker |
| source | ?principal |
| target | <deploy-phase Cloud Build worker (BuildWorker) for the target> |
| permissions | clouddeploy.rollouts.create iam.serviceAccounts.actAs |
| conditions | iam_permission |
| state logic | ACTIVE when ?principal holds effective clouddeploy.rollouts.create AND CanPassIdentity(?principal -> ?deploy_sa) is ACTIVE. CONDITIONAL(approval_required) when the target has requireApproval: true and ?principal does not hold clouddeploy.rollouts.approve — the rollout is queued but cannot proceed without approver action; downgrade to CONDITIONAL. CONDITIONAL(time_window) when a deploy policy restricts rollout creation during the current time window — still possible outside the window. BLOCKED when an IAM deny policy denies clouddeploy.rollouts.create or iam.serviceAccounts.actAs at the effective scope. |
Narrative
{principal.name} can promote a release (clouddeploy.rollouts.create) in pipeline {pipeline.name}, triggering a Cloud Build deploy worker that runs as {deploy_sa.name} (iam.serviceAccounts.actAs required). If the promoted release contains attacker-controlled Skaffold hooks or manifests, code runs as {deploy_sa.name}. Cite cicd-chains cicd-modify-buildspec-executes-as to collapse into CanExecuteAs.
Raw rule rules/derived/gcp/clouddeploy.yaml
id: gcp-deploy-rollout-create-modifies-code
emits: CanModifyCode
description: clouddeploy.rollouts.create (promotion) with actAs on the deploy SA triggers the deploy Cloud
Build worker running as the deploy SA.
applies_to:
- gcp
match:
- - principal: null
- CanPassIdentity
- deploy_sa: null
where:
- ?principal has effective clouddeploy.rollouts.create on the delivery pipeline
- ?deploy_sa is the deploy-phase execution SA for the target being promoted to
- ?deploy_sa is bound via CanPassIdentity through iam.serviceAccounts.actAs (gcp-sa-act-as)
emit:
source_type: Identity
target_type: BuildWorker
source: ?principal
target: <deploy-phase Cloud Build worker (BuildWorker) for the target>
permissions:
- clouddeploy.rollouts.create
- iam.serviceAccounts.actAs
conditions:
- iam_permission
state_logic: "ACTIVE when ?principal holds effective clouddeploy.rollouts.create AND CanPassIdentity(?principal\
\ -> ?deploy_sa) is ACTIVE. CONDITIONAL(approval_required) when the target has requireApproval: true\
\ and ?principal does not hold clouddeploy.rollouts.approve \u2014 the rollout is queued but cannot\
\ proceed without approver action; downgrade to CONDITIONAL. CONDITIONAL(time_window) when a deploy\
\ policy restricts rollout creation during the current time window \u2014 still possible outside the\
\ window. BLOCKED when an IAM deny policy denies clouddeploy.rollouts.create or iam.serviceAccounts.actAs\
\ at the effective scope."
confidence: 0.95
derived_from:
- ?principal CanPassIdentity ?deploy_sa (gcp-sa-act-as)
- clouddeploy.rollouts.create effective permission
false_positive_note: "actAs on the DEPLOY SA (not the render SA) gates rollout creation. An attacker\
\ with releases.create actAs(render SA) but NOT rollouts.create actAs(deploy SA) can only reach the\
\ render SA. The deploy SA's GCP permissions determine the post-escalation blast radius (GKE cluster\
\ access, Cloud Run service update, etc.). The approval gate (requireApproval: true) means the rollout\
\ queues; it does NOT independently yield code execution until an approver acts \u2014 stay CONDITIONAL."
narrative: '{principal.name} can promote a release (clouddeploy.rollouts.create) in pipeline {pipeline.name},
triggering a Cloud Build deploy worker that runs as {deploy_sa.name} (iam.serviceAccounts.actAs required).
If the promoted release contains attacker-controlled Skaffold hooks or manifests, code runs as {deploy_sa.name}.
Cite cicd-chains cicd-modify-buildspec-executes-as to collapse into CanExecuteAs.'