azure-evg-publish-via-key
A principal that holds the topic access key (retrieved via listKeys/action) can publish arbitrary events to the topic over HTTPS, triggering all bound consumers.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?key) ==
AccessKey
?key is a topic access key (key1 or key2) for an Event Grid custom topic or domain topic
?topic is the Event Grid topic or domain that ?key authenticates to
?topic.properties.publicNetworkAccess == Enabled OR principal has network path to topic private endpoint
emit
| source type | Identity |
|---|---|
| target type | GenericData |
| source | ?principal |
| target | ?topic |
| conditions | trigger_exists network_reachability |
| state logic | ACTIVE when the key has been retrieved (CanReadSecret ACTIVE) AND the topic is network-reachable (publicNetworkAccess=Enabled, or principal has private endpoint access). CONDITIONAL(network_reachability) when the topic has publicNetworkAccess= Disabled and no confirmed private endpoint reach. CONDITIONAL(trigger_exists) when the topic has no confirmed live event subscription binding to a consumer (publishing succeeds but no consumer is triggered — still emitted at CONDITIONAL because a subscription may exist or be creatable). Inherit weakest from CanReadSecret. BLOCKED if the key has been rotated after retrieval (key is no longer valid) or if deny assignment blocks listKeys/action (which blocks the prerequisite CanReadSecret). |
Narrative
{principal.name} holds the access key for Event Grid topic {target.name} (retrieved via topics/listKeys/action); it can publish arbitrary events over HTTPS (aeg-sas-key header), triggering all bound event subscription consumers with an attacker-controlled payload. messaging-chains derives CanTrigger(principal->consumer) from this CanWriteData + the existing subscription CanTrigger binding.
Raw rule rules/derived/azure/eventgrid.yaml
id: azure-evg-publish-via-key
emits: CanWriteData
description: A principal that holds the topic access key (retrieved via listKeys/action) can publish arbitrary
events to the topic over HTTPS, triggering all bound consumers.
match:
- - principal: null
- CanReadSecret
- key: null
where:
- node_type(?key) == AccessKey
- ?key is a topic access key (key1 or key2) for an Event Grid custom topic or domain topic
- ?topic is the Event Grid topic or domain that ?key authenticates to
- ?topic.properties.publicNetworkAccess == Enabled OR principal has network path to topic private endpoint
emit:
source_type: Identity
target_type: GenericData
source: ?principal
target: ?topic
permissions: []
conditions:
- trigger_exists
- network_reachability
state_logic: "ACTIVE when the key has been retrieved (CanReadSecret ACTIVE) AND the topic is network-reachable\
\ (publicNetworkAccess=Enabled, or principal has private endpoint access). CONDITIONAL(network_reachability)\
\ when the topic has publicNetworkAccess= Disabled and no confirmed private endpoint reach. CONDITIONAL(trigger_exists)\
\ when the topic has no confirmed live event subscription binding to a consumer (publishing succeeds\
\ but no consumer is triggered \u2014 still emitted at CONDITIONAL because a subscription may exist\
\ or be creatable). Inherit weakest from CanReadSecret. BLOCKED if the key has been rotated after\
\ retrieval (key is no longer valid) or if deny assignment blocks listKeys/action (which blocks the\
\ prerequisite CanReadSecret)."
confidence: min(contributing_confidences) * 0.97
derived_from:
- 'azure-evg-list-keys OR azure-evg-domain-list-keys: ?principal CanReadSecret ?key'
- 'messaging-chains.yaml: messaging-publish-triggers-consumer: CanWriteData + CanTrigger(topic->consumer)
=> CanTrigger(principal->consumer)'
false_positive_note: "Publishing via key does NOT require any ARM RBAC permission at publish time \u2014\
\ it is HTTP authenticated using the key (aeg-sas-key header). The prerequisite is CanReadSecret (listKeys/action),\
\ which retrieves the key. Once the key is in hand, the attacker can publish from any network endpoint\
\ that can reach the topic's public endpoint or private endpoint. Do not list Microsoft.EventGrid/events/send/action\
\ in permissions (that is Entra token-based publish, a different path). A topic with publicNetworkAccess=Disabled\
\ cannot be published to from the internet regardless of key possession; downgrade to CONDITIONAL(network_reachability)\
\ if no confirmed private endpoint access. The key enables unlimited publishing \u2014 no per-event\
\ rate limit that would prevent triggering consumers. Publishing does NOT grant read access to consumer\
\ endpoints (Service Bus queues, Storage queues). The consumer must have a live, enabled event subscription\
\ binding for messaging-chains rule 1 to fire \u2014 verify the binding before marking the full CanTrigger\
\ chain ACTIVE. System topics do not accept publish via key (only first-party services publish); do\
\ not emit for system topics."
narrative: '{principal.name} holds the access key for Event Grid topic {target.name} (retrieved via
topics/listKeys/action); it can publish arbitrary events over HTTPS (aeg-sas-key header), triggering
all bound event subscription consumers with an attacker-controlled payload. messaging-chains derives
CanTrigger(principal->consumer) from this CanWriteData + the existing subscription CanTrigger binding.'