azure-auto-webhook-write-trigger
Create a new webhook for any runbook via automationAccounts/webhooks/write; the attacker receives the webhook URI once and can trigger the runbook.
match (effective permission)
{
"action": "Microsoft.Automation/automationAccounts/webhooks/write",
"scope_type": "resource|resourceGroup|subscription"
}
where
principal effectively holds automationAccounts/webhooks/write at the automationAccount scope
emit
| source type | Identity |
|---|---|
| target type | GenericCompute |
| source | <principal> |
| target | <runbook (BuildWorker) targeted by the new webhook> |
| permissions | Microsoft.Automation/automationAccounts/webhooks/write |
| conditions | service_state |
| state logic | ACTIVE when the principal holds webhooks/write — the attacker can create a new webhook URI for any runbook, receive the URI once at creation, and use it to trigger jobs. CONDITIONAL(service_state) if the account is suspended. BLOCKED if a deny assignment covers webhooks/write. |
Narrative
{principal.name} can create new webhook URIs for runbooks in Automation Account (automationAccounts/webhooks/write); each webhook creation yields a secret URI that can be used to trigger the runbook via HTTP POST as the account's managed identity, bypassing ARM RBAC.
Raw rule rules/derived/azure/automation.yaml
id: azure-auto-webhook-write-trigger
emits: CanTrigger
description: Create a new webhook for any runbook via automationAccounts/webhooks/write; the attacker
receives the webhook URI once and can trigger the runbook.
match_effective_permission:
action: Microsoft.Automation/automationAccounts/webhooks/write
scope_type: resource|resourceGroup|subscription
where:
- principal effectively holds automationAccounts/webhooks/write at the automationAccount scope
emit:
source_type: Identity
target_type: GenericCompute
source: <principal>
target: <runbook (BuildWorker) targeted by the new webhook>
permissions:
- Microsoft.Automation/automationAccounts/webhooks/write
conditions:
- service_state
state_logic: "ACTIVE when the principal holds webhooks/write \u2014 the attacker can create a new webhook\
\ URI for any runbook, receive the URI once at creation, and use it to trigger jobs. CONDITIONAL(service_state)\
\ if the account is suspended. BLOCKED if a deny assignment covers webhooks/write."
confidence: 0.95
derived_from:
- 'effective permission: Microsoft.Automation/automationAccounts/webhooks/write'
- 'cicd-chains.yaml: cicd-trigger-runner-executes-as (webhook URI creation = CanTrigger primitive without
ARM RBAC)'
false_positive_note: "webhooks/write grants the attacker FULL CONTROL to create new webhooks for ANY\
\ runbook in the account. Each webhook creation returns a URI (secrets) once \u2014 the attacker uses\
\ the URI to trigger runbooks via HTTP POST without ARM roles/RBAC. This is distinct from webhooks/read\
\ (metadata read) and from CanTrigger via jobs/write (ARM RBAC trigger). A principal with webhooks/write\
\ can trigger any runbook via this data-plane HTTP surface, independent of jobs/write permission."
narrative: '{principal.name} can create new webhook URIs for runbooks in Automation Account (automationAccounts/webhooks/write);
each webhook creation yields a secret URI that can be used to trigger the runbook via HTTP POST as
the account''s managed identity, bypassing ARM RBAC.'