azure-evg-domain-key-publish-domain
A principal holding the domain access key can publish events to ALL topics within the Event Grid domain, triggering all subscribers across the domain.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?domainkey) ==
AccessKey
?domainkey is a domain-level access key (from azure-evg-domain-list-keys)
?domain is the Event Grid domain whose key was retrieved
?domain.properties.publicNetworkAccess == Enabled OR principal has VNet access to private endpoint
emit
| source type | Identity |
|---|---|
| target type | GenericData |
| source | ?principal |
| target | ?domain |
| conditions | trigger_exists network_reachability |
| state logic | ACTIVE when the domain key has been retrieved (CanReadSecret ACTIVE on domain key) AND the domain is network-reachable. CONDITIONAL(trigger_exists) when no confirmed live subscription on any domain topic routes to a consumer. CONDITIONAL(network_reachability) when publicNetworkAccess=Disabled and no private endpoint access confirmed. The domain key permits publishing to all topics in the domain via the domain endpoint. |
Narrative
{principal.name} holds the domain access key for Event Grid domain {target.name} (retrieved via domains/listKeys/action); publishing to any topic in the domain triggers that topic's bound event subscription consumers with an attacker-controlled payload.
Raw rule rules/derived/azure/eventgrid.yaml
id: azure-evg-domain-key-publish-domain
emits: CanWriteData
description: A principal holding the domain access key can publish events to ALL topics within the Event
Grid domain, triggering all subscribers across the domain.
match:
- - principal: null
- CanReadSecret
- domainkey: null
where:
- node_type(?domainkey) == AccessKey
- ?domainkey is a domain-level access key (from azure-evg-domain-list-keys)
- ?domain is the Event Grid domain whose key was retrieved
- ?domain.properties.publicNetworkAccess == Enabled OR principal has VNet access to private endpoint
emit:
source_type: Identity
target_type: GenericData
source: ?principal
target: ?domain
permissions: []
conditions:
- trigger_exists
- network_reachability
state_logic: ACTIVE when the domain key has been retrieved (CanReadSecret ACTIVE on domain key) AND
the domain is network-reachable. CONDITIONAL(trigger_exists) when no confirmed live subscription on
any domain topic routes to a consumer. CONDITIONAL(network_reachability) when publicNetworkAccess=Disabled
and no private endpoint access confirmed. The domain key permits publishing to all topics in the domain
via the domain endpoint.
confidence: min(contributing_confidences) * 0.96
derived_from:
- 'azure-evg-domain-list-keys: ?principal CanReadSecret ?domainkey'
- 'messaging-chains.yaml: messaging-publish-triggers-consumer: CanWriteData(?p,?domain-topic) + CanTrigger(?domain-topic,?consumer)
=> CanTrigger(?p,?consumer)'
false_positive_note: "Publishing via domain 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\
\ (domains/listKeys/action), which retrieves the key. The domain key has broader blast radius than\
\ per-topic keys: it grants publish access to ALL topics in the domain. The domain key is submitted\
\ to the domain endpoint with a 'topic' field specifying the target domain topic; publishing to all\
\ domain topics requires knowledge of topic names, but these are enumerable via ARM read (domains/topics/read).\
\ Scope: this edge targets the domain node; downstream CanTrigger edges target each topic's consumers.\
\ A principal who can list domain topics and holds the domain key can target any topic in the domain\
\ without per-topic keys."
narrative: '{principal.name} holds the domain access key for Event Grid domain {target.name} (retrieved
via domains/listKeys/action); publishing to any topic in the domain triggers that topic''s bound event
subscription consumers with an attacker-controlled payload.'