gcp-eventarc-cross-project-trust
An IAM binding on an Eventarc trigger granting eventarc.triggers.update (or .create in the project) to a principal in a different project is cross-project trigger-management trust - that external principal can redirect the trigger or bind new sources to consumers in this project.
match (record)
{
"field": "iamPolicy.bindings",
"resource_type": "google.cloud.eventarc.v1.Trigger"
}
where
a binding member (user:, serviceAccount:) belongs to a different project than the trigger
the binding grants roles/eventarc.developer or roles/eventarc.admin (containing eventarc.triggers.update)
emit
| source type | ResourcePolicy |
|---|---|
| target type | Project |
| source | <trigger IAM allow policy (ResourcePolicy)> |
| target | <external project of the granted principal> |
| conditions | resource_policy condition_expression |
| state logic | ACTIVE when the binding unconditionally grants eventarc.triggers.update or eventarc.triggers.create to an external principal. CONDITIONAL(condition_expression) when scoped by an IAM condition (resource tag, request time, originating network). BLOCKED by an org policy or IAM deny that overrides the grant. |
Narrative
The IAM policy of trigger {trigger.name} grants a principal in project {ext_project.name} the ability to update or create Eventarc triggers (roles/eventarc.developer), creating cross-project trigger-management trust; an attacker in that project can redirect this trigger's event stream to attacker-chosen compute in this project.
Raw rule rules/derived/gcp/eventarc.yaml
id: gcp-eventarc-cross-project-trust
emits: CrossProjectTrust
description: "An IAM binding on an Eventarc trigger granting eventarc.triggers.update (or .create in the\
\ project) to a principal in a different project is cross-project trigger-management trust \u2014 that\
\ external principal can redirect the trigger or bind new sources to consumers in this project."
match_record:
resource_type: google.cloud.eventarc.v1.Trigger
field: iamPolicy.bindings
where:
- a binding member (user:, serviceAccount:) belongs to a different project than the trigger
- the binding grants roles/eventarc.developer or roles/eventarc.admin (containing eventarc.triggers.update)
emit:
source_type: ResourcePolicy
target_type: Project
source: <trigger IAM allow policy (ResourcePolicy)>
target: <external project of the granted principal>
permissions: []
conditions:
- resource_policy
- condition_expression
state_logic: ACTIVE when the binding unconditionally grants eventarc.triggers.update or eventarc.triggers.create
to an external principal. CONDITIONAL(condition_expression) when scoped by an IAM condition (resource
tag, request time, originating network). BLOCKED by an org policy or IAM deny that overrides the grant.
derived_from:
- "trigger.iamPolicy.bindings \u2014 cross-project member with trigger-update/create grant"
false_positive_note: "CITE, DO NOT DUPLICATE can-control: this rule asserts ONLY the cross-project trigger\
\ management trust \u2014 it does NOT emit CanEnterProject. The CanEnterProject consequence (external\
\ principal updates trigger \u2192 redirected CanTrigger \u2192 CanExecuteAs runtime SA in this project)\
\ is produced by can-control consuming this CrossProjectTrust together with CanModifyConfiguration\
\ / CanTrigger / ExecutesAs edges. Honor IAM conditions."
narrative: The IAM policy of trigger {trigger.name} grants a principal in project {ext_project.name}
the ability to update or create Eventarc triggers (roles/eventarc.developer), creating cross-project
trigger-management trust; an attacker in that project can redirect this trigger's event stream to
attacker-chosen compute in this project.