azure-aci-execute-as-via-exec
exec in a container + its group runs as an MI => execute as that MI (via IMDS/env token).
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
{'principal': None}
CanExecuteCommand {'container': None}
{'group': None} ContainsResourceReference {'container': None}
{'group': None} ExecutesAs {'mi': None}
where
node_type(?container) ==
Container
node_type(?group) == ContainerService
?mi.privilege_level >= ?principal.privilege_level
optional
Present → upgrade the emitted state; absent → downgrade (not a hard requirement).
{'principal': None}
CanStart {'group': None}
emit
| source type | Identity |
|---|---|
| target type | Identity |
| source | <principal> |
| target | <managed identity> |
| permissions | Microsoft.ContainerInstance/containerGroups/containers/exec/action |
| conditions | service_state |
| state logic | if ?group running then ACTIVE; elif matched(optional[0]) then ACTIVE (attacker can start it); else CONDITIONAL(service_state) |
Narrative
{principal.name} can exec into a container of {group.name} and mint the token of its identity {mi.name} (IMDS / IDENTITY_ENDPOINT), executing as {mi.name}.
Raw rule rules/derived/azure/aci.yaml
id: azure-aci-execute-as-via-exec
emits: CanExecuteAs
description: exec in a container + its group runs as an MI => execute as that MI (via IMDS/env token).
match:
- - principal: null
- CanExecuteCommand
- container: null
- - group: null
- ContainsResourceReference
- container: null
- - group: null
- ExecutesAs
- mi: null
where:
- node_type(?container) == Container
- node_type(?group) == ContainerService
- ?mi.privilege_level >= ?principal.privilege_level
optional:
- - principal: null
- CanStart
- group: null
emit:
source_type: Identity
target_type: Identity
source: <principal>
target: <managed identity>
state_logic: if ?group running then ACTIVE; elif matched(optional[0]) then ACTIVE (attacker can start
it); else CONDITIONAL(service_state)
conditions:
- service_state
conditions_from:
- group: null
- mi: null
permissions:
- Microsoft.ContainerInstance/containerGroups/containers/exec/action
derived_from:
- <CanExecuteCommand edge_id>
- <ContainsResourceReference edge_id>
- <ExecutesAs edge_id>
false_positive_note: Emit only when the group has a managed identity and that MI out-privileges the
caller. On a stopped group without CanStart -> CONDITIONAL(service_state). CanExecuteCommand targets
the Container node (schema-valid target); the containing group carries the ExecutesAs(group -> mi)
fact, joined here via the structural ContainsResourceReference(group -> container) materialized by
azure-aci-group-contains-container.
narrative: '{principal.name} can exec into a container of {group.name} and mint the token of its identity
{mi.name} (IMDS / IDENTITY_ENDPOINT), executing as {mi.name}.'