messaging-publish-triggers-consumer

Publishing/sending to an event source triggers the consumer bound to it (via an event-source-mapping/subscription/rule target) with an attacker-influenced payload.

derived any cloud emits CanTrigger

match

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

{'principal': None} CanWriteData {'src': None} {'src': None} CanTrigger {'consumer': None}

where

node_class(?src) in [Messaging, Storage] node_class(?consumer) == Compute or node_type(?consumer) == Workflow

optional

Present → upgrade the emitted state; absent → downgrade (not a hard requirement).

{'principal': None} CanSchedule {'src': None}

emit

source typeMessaging
target typeCompute
source?principal
target?consumer
conditionstrigger_exists service_state
state logicACTIVE when the event-source binding is confirmed present and the consumer is invocable — the event-source-mapping is ENABLED, the subscription is ACTIVE, or the rule is ENABLED — so a published message actually drives a run. Otherwise CONDITIONAL(trigger_exists): the principal can publish but the binding is disabled/absent (then matched(optional[0]) — the principal can also create/enable the binding — keeps it realizable as CONDITIONAL, not BLOCKED). A source event filter / subscription filter the attacker payload CANNOT satisfy downgrades to CONDITIONAL(condition_expression) or BLOCKED. Inherit weakest with the contributing CanWriteData (a resource-policy/deny-gated publish caps this) and the CanTrigger binding edge.

Narrative

{principal.name} can publish to the event source {src.name} ({perm:CanWriteData}), which is bound to {consumer.name} via an event-source mapping/subscription/rule; a crafted message therefore triggers {consumer.name} to run with an attacker-influenced payload.

Raw rule rules/derived/messaging-chains.yaml

id: messaging-publish-triggers-consumer
emits: CanTrigger
description: Publishing/sending to an event source triggers the consumer bound to it (via an event-source-mapping/subscription/rule
  target) with an attacker-influenced payload.
applies_to:
- '*'
match:
- - principal: null
  - CanWriteData
  - src: null
- - src: null
  - CanTrigger
  - consumer: null
where:
- node_class(?src) in [Messaging, Storage]
- node_class(?consumer) == Compute or node_type(?consumer) == Workflow
optional:
- - principal: null
  - CanSchedule
  - src: null
emit:
  source_type: Messaging
  target_type: Compute
  source: ?principal
  target: ?consumer
  permissions: []
  conditions:
  - trigger_exists
  - service_state
  state_logic: "ACTIVE when the event-source binding is confirmed present and the consumer is invocable\
    \ \u2014 the event-source-mapping is ENABLED, the subscription is ACTIVE, or the rule is ENABLED \u2014\
    \ so a published message actually drives a run. Otherwise CONDITIONAL(trigger_exists): the principal\
    \ can publish but the binding is disabled/absent (then matched(optional[0]) \u2014 the principal can\
    \ also create/enable the binding \u2014 keeps it realizable as CONDITIONAL, not BLOCKED). A source\
    \ event filter / subscription filter the attacker payload CANNOT satisfy downgrades to CONDITIONAL(condition_expression)\
    \ or BLOCKED. Inherit weakest with the contributing CanWriteData (a resource-policy/deny-gated publish\
    \ caps this) and the CanTrigger binding edge."
  confidence: min(contributing_confidences)
  derived_from:
  - ?principal CanWriteData ?src
  - ?src CanTrigger ?consumer
  false_positive_note: "The judgment is (a) the principal can genuinely PUBLISH to ?src (the send action\
    \ \u2014 sqs:SendMessage / sns:Publish / events:PutEvents / kinesis:PutRecord / pubsub.topics.publish\
    \ / ServiceBus/EventGrid/EventHub send \u2014 is granted, not denied by a resource policy) and (b)\
    \ a LIVE binding routes ?src to ?consumer. Do NOT emit ACTIVE for a disabled event-source-mapping,\
    \ an inactive/expired subscription, or a rule whose event pattern the attacker payload cannot match\
    \ \u2014 an event-pattern/subscription filter is a real control (downgrade to CONDITIONAL/BLOCKED).\
    \ A dead-letter-only or archive-only source that never invokes compute is not this edge. This CanTrigger\
    \ feeds rule 2 (and cicd-chains rule 2 where the consumer is a CI runner) for the execute-as consequence;\
    \ it does NOT by itself grant an identity."
  narrative: '{principal.name} can publish to the event source {src.name} ({perm:CanWriteData}), which
    is bound to {consumer.name} via an event-source mapping/subscription/rule; a crafted message therefore
    triggers {consumer.name} to run with an attacker-influenced payload.'
move · open · esc close