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.

derived azure emits CanTrigger

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 typeIdentity
target typeGenericCompute
source<principal>
target<runbook (BuildWorker) targeted by the new webhook>
permissionsMicrosoft.Automation/automationAccounts/webhooks/write
conditionsservice_state
state logicACTIVE 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.'
move · open · esc close