gcp-pubsub-push-triggers-consumer

An active push subscription binding its topic's messages to an HTTP endpoint (Cloud Run service / Cloud Function URL) makes the subscription an event-source bridge: messages published to the topic are delivered to the consumer. Consumed by messaging-chains to derive CanTrigger(publisher → consumer).

derived gcp emits CanTrigger

match

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

{'match_record': {'resource_type': 'google.pubsub.Subscription', 'field': 'pushConfig.pushEndpoint'}, 'where': ['pushConfig.pushEndpoint is non-empty and resolves to a Cloud Run service or Cloud Functions URL', '?subscription.state is ACTIVE (not PAUSED, DELETED)', '?subscription is attached to ?topic (subscription.topic field)']}

where

node_type(?subscription) == Queue node_class(?consumer) == Compute

emit

source typeQueue
target typeCompute
source<Pub/Sub subscription node>
target<Cloud Run service / Cloud Function consumer at the push endpoint URL>
conditionstrigger_exists service_state
state logicACTIVE when the subscription state is ACTIVE and the push endpoint URL resolves to a modeled Cloud Run service or Cloud Function that is enabled/ running. CONDITIONAL(trigger_exists) when the subscription is PAUSED or the endpoint does not resolve to a modeled compute node (external URL or not yet inventoried). CONDITIONAL(condition_expression) when the subscription has a non-trivial message filter (filter field non-empty): the attacker's payload must match the filter expression to be delivered. BLOCKED when the subscription state is DELETED or the push SA is missing actAs (delivery fails silently). Inherit weakest with the contributing CanWriteData edge in messaging-chains.

Narrative

Pub/Sub subscription {subscription.name} is a push subscription delivering to {consumer.name} ({pushEndpoint}); messages published to the topic are POSTed to {consumer.name}, feeding messaging-chains to derive CanTrigger(publisher → {consumer.name}).

Raw rule rules/derived/gcp/pubsub.yaml

id: gcp-pubsub-push-triggers-consumer
emits: CanTrigger
description: "An active push subscription binding its topic's messages to an HTTP endpoint (Cloud Run\
  \ service / Cloud Function URL) makes the subscription an event-source bridge: messages published to\
  \ the topic are delivered to the consumer. Consumed by messaging-chains to derive CanTrigger(publisher\
  \ \u2192 consumer)."
match:
- match_record:
    resource_type: google.pubsub.Subscription
    field: pushConfig.pushEndpoint
  where:
  - pushConfig.pushEndpoint is non-empty and resolves to a Cloud Run service or Cloud Functions URL
  - ?subscription.state is ACTIVE (not PAUSED, DELETED)
  - ?subscription is attached to ?topic (subscription.topic field)
where:
- node_type(?subscription) == Queue
- node_class(?consumer) == Compute
emit:
  source_type: Queue
  target_type: Compute
  source: <Pub/Sub subscription node>
  target: <Cloud Run service / Cloud Function consumer at the push endpoint URL>
  permissions: []
  conditions:
  - trigger_exists
  - service_state
  state_logic: 'ACTIVE when the subscription state is ACTIVE and the push endpoint URL resolves to a modeled
    Cloud Run service or Cloud Function that is enabled/ running. CONDITIONAL(trigger_exists) when the
    subscription is PAUSED or the endpoint does not resolve to a modeled compute node (external URL or
    not yet inventoried). CONDITIONAL(condition_expression) when the subscription has a non-trivial message
    filter (filter field non-empty): the attacker''s payload must match the filter expression to be delivered.
    BLOCKED when the subscription state is DELETED or the push SA is missing actAs (delivery fails silently).
    Inherit weakest with the contributing CanWriteData edge in messaging-chains.'
  confidence: 0.95
  derived_from:
  - pubsub.subscriptions.get[pushConfig.pushEndpoint, state, topic, filter]
  false_positive_note: "Only emit for PUSH subscriptions (pushConfig.pushEndpoint non-empty). Pull subscriptions\
    \ do NOT automatically trigger a consumer \u2014 they require the consumer to actively poll (model\
    \ the consumer's pull action as CanReadData, not CanTrigger). A subscription filter (filter field)\
    \ is a real delivery gate: if the attacker's payload cannot satisfy the filter expression, delivery\
    \ is silently dropped \u2014 downgrade to CONDITIONAL(condition_expression). BigQuery and Cloud Storage\
    \ subscriptions deliver to data sinks, not compute; do not emit CanTrigger \u2192 CanExecuteAs for\
    \ those delivery types. Dead-letter topic forwarding is a separate hop; model it as a new CanTrigger\
    \ chain off the dead-letter topic if that topic also has a consumer."
  narrative: "Pub/Sub subscription {subscription.name} is a push subscription delivering to {consumer.name}\
    \ ({pushEndpoint}); messages published to the topic are POSTed to {consumer.name}, feeding messaging-chains\
    \ to derive CanTrigger(publisher \u2192 {consumer.name})."
move · open · esc close