azure-auto-credential-read
Read Automation Credentials (username/password pairs) via automationAccounts/credentials/read; values require data-plane getProperties/action or runbook execution.
match (effective permission)
{
"action": "Microsoft.Automation/automationAccounts/credentials/read",
"scope_type": "resource|resourceGroup|subscription"
}
where
principal effectively holds automationAccounts/credentials/read at the automationAccount scope
emit
| source type | Identity |
|---|---|
| target type | Secret |
| source | <principal> |
| target | <Automation Credential (Secret)> |
| permissions | Microsoft.Automation/automationAccounts/credentials/read |
| conditions | key_permission |
| state logic | CONDITIONAL(key_permission) — ARM read (credentials/read) returns credential names but NOT values. The values require either (a) the additional data-plane permission automationAccounts/credentials/getProperties/action (uncommon; requires explicit data-plane RBAC) OR (b) code execution in a runbook (Get-AutomationCredential returns the value). Confidence 0.70 reflects the data-plane gate. Only ACTIVE if the principal also holds getProperties/action OR can execute code in the sandbox (CanModifyCode or CanTrigger with attacker code). BLOCKED if a deny assignment covers credentials/read. |
Narrative
{principal.name} can read Automation Credentials in the account (automationAccounts/credentials/read); credential names are visible in ARM, but values require either data-plane getProperties/action or runbook code execution.
Raw rule rules/derived/azure/automation.yaml
id: azure-auto-credential-read
emits: CanReadSecret
description: Read Automation Credentials (username/password pairs) via automationAccounts/credentials/read;
values require data-plane getProperties/action or runbook execution.
match_effective_permission:
action: Microsoft.Automation/automationAccounts/credentials/read
scope_type: resource|resourceGroup|subscription
where:
- principal effectively holds automationAccounts/credentials/read at the automationAccount scope
emit:
source_type: Identity
target_type: Secret
source: <principal>
target: <Automation Credential (Secret)>
permissions:
- Microsoft.Automation/automationAccounts/credentials/read
conditions:
- key_permission
state_logic: "CONDITIONAL(key_permission) \u2014 ARM read (credentials/read) returns credential names\
\ but NOT values. The values require either (a) the additional data-plane permission automationAccounts/credentials/getProperties/action\
\ (uncommon; requires explicit data-plane RBAC) OR (b) code execution in a runbook (Get-AutomationCredential\
\ returns the value). Confidence 0.70 reflects the data-plane gate. Only ACTIVE if the principal also\
\ holds getProperties/action OR can execute code in the sandbox (CanModifyCode or CanTrigger with\
\ attacker code). BLOCKED if a deny assignment covers credentials/read."
confidence: 0.7
derived_from:
- 'effective permission: Microsoft.Automation/automationAccounts/credentials/read'
- 'credential-chains.yaml: read-secret-yields-identity (CanReadSecret + CredentialsFor => CanImpersonate)'
false_positive_note: "Emit at CONDITIONAL(key_permission) because ARM credentials/read alone does NOT\
\ return the credential value \u2014 it only enumerates credential names. To retrieve the password,\
\ the principal needs EITHER (a) the separate data-plane action automationAccounts/credentials/getProperties/action\
\ (not implied by credentials/read) OR (b) code execution in the sandbox to call Get-AutomationCredential.\
\ Credentials are commonly database credentials, AD passwords, or third-party API keys stored in the\
\ Automation Credential store \u2014 high-value targets. Do not mark ACTIVE unless the attacker also\
\ holds getProperties/action or can execute code."
narrative: '{principal.name} can read Automation Credentials in the account (automationAccounts/credentials/read);
credential names are visible in ARM, but values require either data-plane getProperties/action or
runbook code execution.'