azure-arm-deploymentscript-attach-uami
Principal holds assign/action on a UAMI and deploymentScripts/write - can bind the UAMI to a new or existing deploymentScript, making it the script's execution identity.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?script) in [
BuildWorker, ContainerTask] # Microsoft.Resources/deploymentScripts
node_type(?uami) == ManagedIdentity
?principal has EFFECTIVE Microsoft.ManagedIdentity/userAssignedIdentities/assign/action on ?uami
?principal has EFFECTIVE Microsoft.Resources/deploymentScripts/write on ?script
emit
| source type | Identity |
|---|---|
| target type | ManagedIdentity |
| source | <principal> |
| target | <user-assigned managed identity (UAMI)> |
| permissions | Microsoft.ManagedIdentity/userAssignedIdentities/assign/action Microsoft.Resources/deploymentScripts/write |
| conditions | role_compatibility iam_permission |
| state logic | ACTIVE when BOTH permissions are confirmed: assign/action on the target UAMI AND deploymentScripts/write on the script resource. CONDITIONAL(role_compatibility) when assign/action on the UAMI is not confirmed (ARM rejects the deployment without it). CONDITIONAL(iam_permission) when deploymentScripts/write is not confirmed at the script's scope. BLOCKED if a deny assignment covers either action. |
Narrative
{principal.name} can bind user-assigned MI {uami.name} to deploymentScript {script.name} (assign/action on UAMI + deploymentScripts/write); the ACI container will run as {uami.name}, executing attacker-controlled code as that identity.
Raw rule rules/derived/azure/arm-deployments.yaml
id: azure-arm-deploymentscript-attach-uami
emits: CanPassIdentity
description: "Principal holds assign/action on a UAMI and deploymentScripts/write \u2014 can bind the\
\ UAMI to a new or existing deploymentScript, making it the script's execution identity."
match:
- - principal: null
- CanModifyCode
- script: null
- - script: null
- AttachedTo
- uami: null
where:
- 'node_type(?script) in [BuildWorker, ContainerTask] # Microsoft.Resources/deploymentScripts'
- node_type(?uami) == ManagedIdentity
- ?principal has EFFECTIVE Microsoft.ManagedIdentity/userAssignedIdentities/assign/action on ?uami
- ?principal has EFFECTIVE Microsoft.Resources/deploymentScripts/write on ?script
emit:
source_type: Identity
target_type: ManagedIdentity
source: <principal>
target: <user-assigned managed identity (UAMI)>
permissions:
- Microsoft.ManagedIdentity/userAssignedIdentities/assign/action
- Microsoft.Resources/deploymentScripts/write
conditions:
- role_compatibility
- iam_permission
state_logic: 'ACTIVE when BOTH permissions are confirmed: assign/action on the target UAMI AND deploymentScripts/write
on the script resource. CONDITIONAL(role_compatibility) when assign/action on the UAMI is not confirmed
(ARM rejects the deployment without it). CONDITIONAL(iam_permission) when deploymentScripts/write
is not confirmed at the script''s scope. BLOCKED if a deny assignment covers either action.'
false_positive_note: "CITE identity-escalation.yaml azure-assign-user-assigned-mi for the general UAMI\
\ assign/action + compute-write CanPassIdentity primitive; this rule is the ARM-deployment-specific\
\ framing (deploymentScripts/write as the compute-write complement). Both permissions are REQUIRED\
\ \u2014 neither alone attaches the UAMI to the script. Dedupes with azure-assign-user-assigned-mi\
\ on (CanPassIdentity, ?principal, ?uami) when both fire; emit once."
narrative: '{principal.name} can bind user-assigned MI {uami.name} to deploymentScript {script.name}
(assign/action on UAMI + deploymentScripts/write); the ACI container will run as {uami.name}, executing
attacker-controlled code as that identity.'
derived_from:
- 'identity-escalation.yaml: azure-assign-user-assigned-mi (general UAMI CanPassIdentity)'
- <CanModifyCode edge on ?script>