gcp-dm-sa-can-set-iam-policy-resource

The Google APIs service agent's effective permissions include *.setIamPolicy on resources it manages when it holds roles/editor (GCS, SA, Pub/Sub, etc.). A DM config can instruct the SA to call setIamPolicy, granting the deployer any role on those resources.

derived gcp emits CanGrantPermission

match

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

{'deployment': None} ExecutesAs {'sa': None}

where

node_type(?deployment) == BuildWorker # DM Deployment node ?sa is the Google APIs service agent (cloudservices SA) for the project ?sa holds roles/editor OR a custom role that includes *.setIamPolicy on resource-level targets a deployment config or accessControl section instructs DM to call setIamPolicy on a resource in the project

emit

source typeServiceAccount
target typeIdentity
source<cloudservices ServiceAccount>
target<attacker-controlled principal named in the accessControl config binding (on a resource)>
permissionsstorage.buckets.setIamPolicy iam.serviceAccounts.setIamPolicy pubsub.topics.setIamPolicy
conditionsiam_permission
state logicACTIVE when the SA holds roles/editor (includes resource-level setIamPolicy). CONDITIONAL(iam_permission) if the SA's effective roles are unknown or restricted by org policy (iam.automaticIamGrantsForDefaultServiceAccounts). BLOCKED if an IAM deny policy denies setIamPolicy at the resource scope.

Narrative

The Google APIs service agent {sa.name} (roles/editor) can call setIamPolicy on {resource.name} as part of a Deployment Manager deployment. A deployer can use this to grant any principal elevated roles on that resource.

Raw rule rules/derived/gcp/deploymentmanager.yaml

id: gcp-dm-sa-can-set-iam-policy-resource
emits: CanGrantPermission
description: The Google APIs service agent's effective permissions include *.setIamPolicy on resources
  it manages when it holds roles/editor (GCS, SA, Pub/Sub, etc.). A DM config can instruct the SA to call
  setIamPolicy, granting the deployer any role on those resources.
match:
- - deployment: null
  - ExecutesAs
  - sa: null
where:
- 'node_type(?deployment) == BuildWorker  # DM Deployment node'
- ?sa is the Google APIs service agent (cloudservices SA) for the project
- ?sa holds roles/editor OR a custom role that includes *.setIamPolicy on resource-level targets
- a deployment config or accessControl section instructs DM to call setIamPolicy on a resource in the
  project
emit:
  source_type: ServiceAccount
  target_type: Identity
  source: <cloudservices ServiceAccount>
  target: <attacker-controlled principal named in the accessControl config binding (on a resource)>
  permissions:
  - storage.buckets.setIamPolicy
  - iam.serviceAccounts.setIamPolicy
  - pubsub.topics.setIamPolicy
  conditions:
  - iam_permission
  state_logic: ACTIVE when the SA holds roles/editor (includes resource-level setIamPolicy). CONDITIONAL(iam_permission)
    if the SA's effective roles are unknown or restricted by org policy (iam.automaticIamGrantsForDefaultServiceAccounts).
    BLOCKED if an IAM deny policy denies setIamPolicy at the resource scope.
  confidence: 0.9
  derived_from:
  - ?deployment ExecutesAs ?sa
  false_positive_note: Scoped to resource-level targets only (GCS buckets, SAs, Pub/Sub topics). Editor
    includes these resource-level permissions. Verify the SA's actual bindings from the project IAM policy.
    This edge is the SA's capability; the DEPLOYER inherits it transitively via CanExecuteAs (deployer
    -> SA) -> CanGrantPermission(SA -> resource). The deployer-level CanGrantPermission is produced by
    the linchpin roll-up, not this rule.
  narrative: The Google APIs service agent {sa.name} (roles/editor) can call setIamPolicy on {resource.name}
    as part of a Deployment Manager deployment. A deployer can use this to grant any principal elevated
    roles on that resource.
move · open · esc close