azure-acr-list-credentials
registries/listCredentials/action allows a principal to retrieve the admin account's long-lived passwords.
match (effective permission)
{
"action": "Microsoft.ContainerRegistry/registries/listCredentials/action",
"scope_type": "resource|resourceGroup|subscription"
}
where
principal effectively holds AcrPush, Contributor, Owner, or a custom role including Microsoft.
ContainerRegistry/registries/listCredentials/action
registry.adminUserEnabled == true
emit
| source type | Identity |
|---|---|
| target type | Credential |
| source | <principal holding listCredentials/action> |
| target | <admin account password Credential> |
| permissions | Microsoft.ContainerRegistry/registries/listCredentials/action |
| state logic | ACTIVE when adminUserEnabled == true and the principal holds listCredentials/action. CONDITIONAL(service_state) when adminUserEnabled == false — the action succeeds but the returned passwords are disabled and cannot authenticate. If a principal holds CanModifyConfiguration on the registry (registries/write), they can upgrade adminUserEnabled false → true, converting CONDITIONAL to ACTIVE. |
Narrative
{source.name} can retrieve {target.name} (the admin account passwords) via registries/listCredentials/action; when adminUserEnabled == true, this retrieval enables persistent HTTP Basic authentication to push, pull, or delete any image in {registry.name} from any network location without an Entra token. credential-chains will derive CanImpersonate when the credential CredentialsFor an identity.
Raw rule rules/derived/azure/acr.yaml
id: azure-acr-list-credentials
emits: CanReadCredential
description: registries/listCredentials/action allows a principal to retrieve the admin account's long-lived
passwords.
match_effective_permission:
action: Microsoft.ContainerRegistry/registries/listCredentials/action
scope_type: resource|resourceGroup|subscription
where:
- principal effectively holds AcrPush, Contributor, Owner, or a custom role including Microsoft.ContainerRegistry/registries/listCredentials/action
- registry.adminUserEnabled == true
emit:
source_type: Identity
target_type: Credential
source: <principal holding listCredentials/action>
target: <admin account password Credential>
permissions:
- Microsoft.ContainerRegistry/registries/listCredentials/action
state_logic: "ACTIVE when adminUserEnabled == true and the principal holds listCredentials/action. CONDITIONAL(service_state)\
\ when adminUserEnabled == false \u2014 the action succeeds but the returned passwords are disabled\
\ and cannot authenticate. If a principal holds CanModifyConfiguration on the registry (registries/write),\
\ they can upgrade adminUserEnabled false \u2192 true, converting CONDITIONAL to ACTIVE."
confidence: 0.95
derived_from:
- "azure-acr-admin-credential-present (explicit rule \u2014 emits ContainsCredential(registry \u2192\
\ admin credential))"
- "credential-chains read-secret-yields-identity (CITED \u2014 consumes CanReadCredential + CredentialsFor\
\ to produce CanImpersonate)"
false_positive_note: "Admin account disabled (adminUserEnabled == false) => passwords are returned by\
\ the API but cannot be used for authentication \u2014 emit CONDITIONAL(service_state), never ACTIVE.\
\ Only emit ACTIVE when adminUserEnabled == true is confirmed in the registry properties. The admin\
\ account is a SINGLE account (username is the registry name); both passwords are long-lived and are\
\ rotated by regenerating them via regenerateCredential/action \u2014 rotating one does NOT invalidate\
\ the other. Long-lived credential = persistent exfiltration risk with no session TTL."
narrative: '{source.name} can retrieve {target.name} (the admin account passwords) via registries/listCredentials/action;
when adminUserEnabled == true, this retrieval enables persistent HTTP Basic authentication to push,
pull, or delete any image in {registry.name} from any network location without an Entra token. credential-chains
will derive CanImpersonate when the credential CredentialsFor an identity.'