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.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
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. |
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.