gcp-deploy-release-create-modifies-code

clouddeploy.releases.create with actAs on the render SA injects attacker-controlled Skaffold config/hooks into the render Cloud Build worker.

derived gcp emits CanModifyCode

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'principal': None} CanPassIdentity {'render_sa': None}

where

?principal has effective clouddeploy.releases.create on the delivery pipeline ?render_sa is the render-phase execution SA for the pipeline's first target ?render_sa is bound via CanPassIdentity through iam.serviceAccounts.actAs (gcp-sa-act-as)

emit

source typeIdentity
target typeBuildWorker
source?principal
target<render-phase Cloud Build worker (BuildWorker) for the delivery pipeline>
permissionsclouddeploy.releases.create iam.serviceAccounts.actAs
conditionsiam_permission
state logicACTIVE when ?principal holds effective clouddeploy.releases.create AND CanPassIdentity(?principal -> ?render_sa) is ACTIVE (iam.serviceAccounts.actAs confirmed on ?render_sa). CONDITIONAL(iam_permission) when actAs is unconfirmed (runtime SA lookup inconclusive). BLOCKED when an IAM deny policy or org policy denies either permission.

Narrative

{principal.name} can create a Cloud Deploy release (clouddeploy.releases.create) with attacker-controlled Skaffold configuration, injecting arbitrary code into the render Cloud Build worker that runs as {render_sa.name}. actAs on {render_sa.name} is required (iam.serviceAccounts.actAs). Cite cicd-chains cicd-modify-buildspec-executes-as to collapse CanModifyCode + ExecutesAs into CanExecuteAs({principal} → {render_sa}).

Raw rule rules/derived/gcp/clouddeploy.yaml

id: gcp-deploy-release-create-modifies-code
emits: CanModifyCode
description: clouddeploy.releases.create with actAs on the render SA injects attacker-controlled Skaffold
  config/hooks into the render Cloud Build worker.
applies_to:
- gcp
match:
- - principal: null
  - CanPassIdentity
  - render_sa: null
where:
- ?principal has effective clouddeploy.releases.create on the delivery pipeline
- ?render_sa is the render-phase execution SA for the pipeline's first target
- ?render_sa is bound via CanPassIdentity through iam.serviceAccounts.actAs (gcp-sa-act-as)
emit:
  source_type: Identity
  target_type: BuildWorker
  source: ?principal
  target: <render-phase Cloud Build worker (BuildWorker) for the delivery pipeline>
  permissions:
  - clouddeploy.releases.create
  - iam.serviceAccounts.actAs
  conditions:
  - iam_permission
  state_logic: ACTIVE when ?principal holds effective clouddeploy.releases.create AND CanPassIdentity(?principal
    -> ?render_sa) is ACTIVE (iam.serviceAccounts.actAs confirmed on ?render_sa). CONDITIONAL(iam_permission)
    when actAs is unconfirmed (runtime SA lookup inconclusive). BLOCKED when an IAM deny policy or org
    policy denies either permission.
  confidence: 0.95
  derived_from:
  - ?principal CanPassIdentity ?render_sa (gcp-sa-act-as)
  - clouddeploy.releases.create effective permission
  false_positive_note: "actAs on the render SA is the mandatory gate \u2014 without it the releases.create\
    \ API call is rejected. Do NOT emit without confirmed CanPassIdentity. The render SA and deploy SA\
    \ may differ; this edge applies only to the RENDER phase worker. Skaffold hooks (before/after deploy\
    \ hooks, custom actions) execute inside the Cloud Build worker; control of skaffold.yaml is full code\
    \ execution as the SA."
  narrative: "{principal.name} can create a Cloud Deploy release (clouddeploy.releases.create) with attacker-controlled\
    \ Skaffold configuration, injecting arbitrary code into the render Cloud Build worker that runs as\
    \ {render_sa.name}. actAs on {render_sa.name} is required (iam.serviceAccounts.actAs). Cite cicd-chains\
    \ cicd-modify-buildspec-executes-as to collapse CanModifyCode + ExecutesAs into CanExecuteAs({principal}\
    \ \u2192 {render_sa})."
move · open · esc close