aws-sns-subscription-trigger

A confirmed active SNS subscription binds the topic to its consumer; every Publish invokes the consumer with the message payload.

derived aws emits CanTrigger

match

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

{'topic': None} HasPolicy {'subscription': None}

where

node_type(?topic) == Topic node_provider(?topic) == aws node_type(?subscription) == EventRule # AWS::SNS::Subscription ?subscription.Protocol in [lambda, sqs] # Lambda and SQS are the compute/execution-relevant paths ?subscription.SubscriptionArn is confirmed (not PendingConfirmation, not Deleted) ?consumer is the node corresponding to ?subscription.Endpoint (lambda function ARN or SQS queue ARN)

emit

source typeTopic
target typeCompute
source?topic
target?consumer
conditionstrigger_exists service_state
state logicACTIVE when the subscription SubscriptionArn is confirmed and not in PendingConfirmation or Deleted state, AND the consumer (Lambda function or SQS queue) is enabled/active. CONDITIONAL(trigger_exists) when the subscription exists but the consumer is disabled, throttled, or the event-source-mapping consuming the SQS queue is disabled. CONDITIONAL(condition_expression) when a non-empty FilterPolicy is set on the subscription — not all messages will be delivered; an attacker must craft a message whose attributes satisfy the filter. POTENTIAL(trigger_exists) for a pending (unconfirmed) subscription. Note: for SQS subscribers, the actual execution identity is on the SQS consumer (Lambda ESM, ECS poller) — this edge models the SNS-to-SQS delivery binding; the SQS-to-consumer binding is the SQS adapter's job.

Narrative

SNS topic {topic.name} has a confirmed subscription to {consumer.name} (Protocol {subscription.Protocol}); every sns:Publish call fans out to {consumer.name}, invoking it with the message as payload. Combined with CanWriteData(publisher, topic) via messaging-chains rule 1, this derives CanTrigger(publisher, {consumer.name}).

Raw rule rules/derived/aws/sns.yaml

id: aws-sns-subscription-trigger
emits: CanTrigger
description: A confirmed active SNS subscription binds the topic to its consumer; every Publish invokes
  the consumer with the message payload.
match:
- - topic: null
  - HasPolicy
  - subscription: null
where:
- node_type(?topic) == Topic
- node_provider(?topic) == aws
- 'node_type(?subscription) == EventRule  # AWS::SNS::Subscription'
- '?subscription.Protocol in [lambda, sqs]  # Lambda and SQS are the compute/execution-relevant paths'
- ?subscription.SubscriptionArn is confirmed (not PendingConfirmation, not Deleted)
- ?consumer is the node corresponding to ?subscription.Endpoint (lambda function ARN or SQS queue ARN)
emit:
  source_type: Topic
  target_type: Compute
  source: ?topic
  target: ?consumer
  permissions: []
  conditions:
  - trigger_exists
  - service_state
  state_logic: "ACTIVE when the subscription SubscriptionArn is confirmed and not in PendingConfirmation\
    \ or Deleted state, AND the consumer (Lambda function or SQS queue) is enabled/active. CONDITIONAL(trigger_exists)\
    \ when the subscription exists but the consumer is disabled, throttled, or the event-source-mapping\
    \ consuming the SQS queue is disabled. CONDITIONAL(condition_expression) when a non-empty FilterPolicy\
    \ is set on the subscription \u2014 not all messages will be delivered; an attacker must craft a message\
    \ whose attributes satisfy the filter. POTENTIAL(trigger_exists) for a pending (unconfirmed) subscription.\
    \ Note: for SQS subscribers, the actual execution identity is on the SQS consumer (Lambda ESM, ECS\
    \ poller) \u2014 this edge models the SNS-to-SQS delivery binding; the SQS-to-consumer binding is\
    \ the SQS adapter's job."
  confidence: 0.95
  derived_from:
  - ?topic HasPolicy ?subscription (confirmed active)
  false_positive_note: "CRITICAL: only emit ACTIVE for subscriptions where SubscriptionArn is a real confirmed\
    \ ARN (not the literal string \"PendingConfirmation\"). Pending subscriptions have not been confirmed\
    \ by the endpoint and will NOT receive messages \u2014 downgrade to POTENTIAL(trigger_exists) at most.\
    \ FilterPolicy: when a non-empty FilterPolicy is present, an attacker who cannot produce a message\
    \ with matching MessageAttributes cannot trigger the consumer through normal delivery \u2014 downgrade\
    \ to CONDITIONAL(condition_expression). Conservative default: treat any non-empty FilterPolicy as\
    \ CONDITIONAL unless the FilterPolicy is verified to be trivially satisfiable by an arbitrary Publish\
    \ call. FIFO topics (standard Lambda subscription not supported directly): do not emit CanTrigger(fifo_topic\
    \ -> lambda) without a SQS FIFO intermediary."
  narrative: SNS topic {topic.name} has a confirmed subscription to {consumer.name} (Protocol {subscription.Protocol});
    every sns:Publish call fans out to {consumer.name}, invoking it with the message as payload. Combined
    with CanWriteData(publisher, topic) via messaging-chains rule 1, this derives CanTrigger(publisher,
    {consumer.name}).
move · open · esc close