azure-vm-execute-as-via-attach-mi
Attach a privileged user-assigned MI to an existing VM the caller can run code on, then execute as that MI via IMDS.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
{'principal': None}
CanPassIdentity {'userMI': None}
{'principal': None} CanAttachIdentity {'vm': None}
{'principal': None} CanExecuteCommand {'vm': None}
where
node_type(?vm) ==
VirtualMachine
?userMI.privilege_level >= ?principal.privilege_level # escalation only
emit
| source type | Identity |
|---|---|
| target type | Identity |
| source | <principal> |
| target | <user-assigned managed identity> |
| permissions | Microsoft.ManagedIdentity/userAssignedIdentities/assign/action Microsoft.Compute/virtualMachines/write runCommand/extensions |
| conditions | role_compatibility |
Narrative
{principal.name} can attach user-assigned MI {userMI.name} to VM {vm.name} it can run code on, then mint {userMI.name}'s token from IMDS, executing as {userMI.name}.
Raw rule rules/derived/azure/vm.yaml
id: azure-vm-execute-as-via-attach-mi
emits: CanExecuteAs
description: Attach a privileged user-assigned MI to an existing VM the caller can run code on, then execute
as that MI via IMDS.
match:
- - principal: null
- CanPassIdentity
- userMI: null
- - principal: null
- CanAttachIdentity
- vm: null
- - principal: null
- CanExecuteCommand
- vm: null
where:
- node_type(?vm) == VirtualMachine
- '?userMI.privilege_level >= ?principal.privilege_level # escalation only'
emit:
source_type: Identity
target_type: Identity
source: <principal>
target: <user-assigned managed identity>
permissions:
- Microsoft.ManagedIdentity/userAssignedIdentities/assign/action
- Microsoft.Compute/virtualMachines/write
- runCommand/extensions
conditions:
- role_compatibility
derived_from:
- <CanPassIdentity edge_id>
- <CanAttachIdentity edge_id>
- <CanExecuteCommand edge_id>
false_positive_note: Requires the attach chain (CanPassIdentity via assign/action + VM write) AND a
code-exec primitive on that VM. This is the EXISTING-VM chain (attach MI, then run) so it emits CanExecuteAs,
not CanCreateWorkloadAs. Escalation only if the attached MI out-privileges the caller.
narrative: '{principal.name} can attach user-assigned MI {userMI.name} to VM {vm.name} it can run code
on, then mint {userMI.name}''s token from IMDS, executing as {userMI.name}.'