gcp-eventarc-publish-to-transport-topic
pubsub.topics.publish on the Eventarc-managed transport Pub/Sub topic lets an attacker inject crafted CloudEvent messages directly into the Eventarc delivery pipeline, bypassing the standard source adapter.
match (effective permission)
{
"action": "pubsub.topics.publish",
"resource_type": "google.pubsub.v1.Topic"
}
where
the target
Topic is the transport.pubsub.topic of an active Eventarc trigger
emit
| source type | Identity |
|---|---|
| target type | Topic |
| source | <principal> |
| target | <Eventarc transport Pub/Sub topic backing the trigger's event pipeline> |
| permissions | pubsub.topics.publish |
| conditions | iam_permission resource_policy |
| state logic | ACTIVE when the principal holds pubsub.topics.publish on the transport topic AND the topic's IAM policy grants this to the principal (the transport topic typically restricts publish to the Eventarc P4SA and source adapter SAs). CONDITIONAL(resource_policy) in all other cases — validate the topic IAM before emitting ACTIVE. BLOCKED when the topic policy denies publish to the principal. |
Narrative
{principal.name} can publish directly to the Eventarc transport Pub/Sub topic {topic.name} (pubsub.topics.publish), injecting crafted CloudEvent messages that bypass the standard source adapter and fire the bound trigger {trigger.name}.
Raw rule rules/derived/gcp/eventarc.yaml
id: gcp-eventarc-publish-to-transport-topic
emits: CanWriteData
description: pubsub.topics.publish on the Eventarc-managed transport Pub/Sub topic lets an attacker inject
crafted CloudEvent messages directly into the Eventarc delivery pipeline, bypassing the standard source
adapter.
match_effective_permission:
action: pubsub.topics.publish
resource_type: google.pubsub.v1.Topic
where:
- the target Topic is the transport.pubsub.topic of an active Eventarc trigger
emit:
source_type: Identity
target_type: Topic
source: <principal>
target: <Eventarc transport Pub/Sub topic backing the trigger's event pipeline>
permissions:
- pubsub.topics.publish
conditions:
- iam_permission
- resource_policy
state_logic: "ACTIVE when the principal holds pubsub.topics.publish on the transport topic AND the topic's\
\ IAM policy grants this to the principal (the transport topic typically restricts publish to the\
\ Eventarc P4SA and source adapter SAs). CONDITIONAL(resource_policy) in all other cases \u2014 validate\
\ the topic IAM before emitting ACTIVE. BLOCKED when the topic policy denies publish to the principal."
derived_from:
- 'effective permission: pubsub.topics.publish on the transport topic (confirmed by topic IAM policy)'
false_positive_note: "This is a HIGH false-positive surface. The Eventarc P4SA (service-PROJECT_NUMBER@\
\ gcp-sa-eventarc.iam.gserviceaccount.com) manages the transport topic; the topic IAM typically grants\
\ pubsub.topics.publish ONLY to the P4SA and/or the source adapter SA (Cloud Logging SA for Audit\
\ Log triggers, Cloud Storage SA for GCS triggers). Do NOT emit ACTIVE without confirming the topic's\
\ IAM policy grants publish to the principal. Inject via this path bypasses event filter matching\
\ in some Eventarc configurations \u2014 condition_expression gate may apply. This CanWriteData feeds\
\ messaging-chains rule 1 with the CanTrigger(transport topic \u2192 consumer) chain."
narrative: '{principal.name} can publish directly to the Eventarc transport Pub/Sub topic {topic.name}
(pubsub.topics.publish), injecting crafted CloudEvent messages that bypass the standard source adapter
and fire the bound trigger {trigger.name}.'