gcp-composer-bucket-set-iam-policy

storage.buckets.setIamPolicy on the Composer environment GCS bucket lets the principal grant storage.objects.create (dags/ write access) to itself or others, enabling the DAG-write code-execution path.

derived gcp emits CanGrantPermission

match (effective permission)

{ "action": "storage.buckets.setIamPolicy", "resource_type": "google.storage.Bucket" }

where

bucket is the environment's DAG bucket (dagGcsPrefix bucket)

emit

source typeIdentity
target typeIdentity
source<principal>
target<principal (self-grant)>
permissionsstorage.buckets.setIamPolicy
conditionsiam_permission
state logicACTIVE when storage.buckets.setIamPolicy is confirmed in the effective grant on the environment bucket. The principal can grant itself (or others) the storage.objects.create permission on the dags/ prefix, enabling the DAG-write code-execution path. BLOCKED if an IAM deny policy applies to storage.buckets.setIamPolicy.

Narrative

{principal.name} holds storage.buckets.setIamPolicy on Composer environment {env.name}'s GCS bucket and can grant itself storage.objects.create on the dags/ prefix, enabling DAG-write remote code execution as environment SA {sa.name}.

Raw rule rules/derived/gcp/composer.yaml

id: gcp-composer-bucket-set-iam-policy
emits: CanGrantPermission
description: storage.buckets.setIamPolicy on the Composer environment GCS bucket lets the principal grant
  storage.objects.create (dags/ write access) to itself or others, enabling the DAG-write code-execution
  path.
match_effective_permission:
  action: storage.buckets.setIamPolicy
  resource_type: google.storage.Bucket
where:
- bucket is the environment's DAG bucket (dagGcsPrefix bucket)
emit:
  source_type: Identity
  target_type: Identity
  source: <principal>
  target: <principal (self-grant)>
  permissions:
  - storage.buckets.setIamPolicy
  conditions:
  - iam_permission
  state_logic: ACTIVE when storage.buckets.setIamPolicy is confirmed in the effective grant on the environment
    bucket. The principal can grant itself (or others) the storage.objects.create permission on the dags/
    prefix, enabling the DAG-write code-execution path. BLOCKED if an IAM deny policy applies to storage.buckets.setIamPolicy.
  confidence: 0.9
  derived_from:
  - <storage.buckets.setIamPolicy effective permission on environment bucket>
  false_positive_note: 'setIamPolicy on the bucket is a powerful primitive: it allows granting storage.objects.create
    to arbitrary principals (including the attacker themselves), which enables the DAG-write escalation.
    This is a two-step path (grant + write) but both steps are under attacker control once setIamPolicy
    is held. Flag alongside the CanModifyCode rule (gcp-composer-dag-write-modify-code) as a chained escalation.
    Org policy constraints.storage.restrictAuthTypes may limit IAM grant targets.'
  narrative: '{principal.name} holds storage.buckets.setIamPolicy on Composer environment {env.name}''s
    GCS bucket and can grant itself storage.objects.create on the dags/ prefix, enabling DAG-write remote
    code execution as environment SA {sa.name}.'
move · open · esc close