azure-aci-imds-token

Any code in a container group can mint a bearer token for each bound managed identity (Linux IMDS, Windows IDENTITY_ENDPOINT).

derived azure emits CanRetrieveToken

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'group': None} ExecutesAs {'mi': None}

emit

source<containerGroup>
target<managed identity bound to the group>

Narrative

Any code running in {group.name} can request a bearer token for {mi.name} (Linux IMDS / Windows IDENTITY_ENDPOINT) with no OS credential.

Raw rule rules/derived/azure/aci.yaml

id: azure-aci-imds-token
emits: CanRetrieveToken
description: Any code in a container group can mint a bearer token for each bound managed identity (Linux
  IMDS, Windows IDENTITY_ENDPOINT).
match:
- - group: null
  - ExecutesAs
  - mi: null
emit:
  source: <containerGroup>
  target: <managed identity bound to the group>
  permissions: []
  note: 'Linux: GET http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=<aud>
    with header ''Metadata: true'' (add client_id= for user-assigned). Windows: fetch from IDENTITY_ENDPOINT
    with header X-IDENTITY-HEADER=IDENTITY_HEADER (env vars injected by Azure). The paired credential-leak
    fact ExposesCredential(group -> mi) is produced by azure-aci-imds-exposescred.'
  false_positive_note: "Only fires when the group actually has a managed identity (identity.type != None).\
    \ No MI => no token; do NOT emit. Windows containers have no 169.254.169.254 endpoint \u2014 capability\
    \ is identical but the mechanism is the injected env vars."
  narrative: Any code running in {group.name} can request a bearer token for {mi.name} (Linux IMDS / Windows
    IDENTITY_ENDPOINT) with no OS credential.
move · open · esc close