azure-arm-deployment-outputs-secret
Principal with deployments/read can retrieve sensitive values (listKeys results, Key Vault references) stored in deployment output history.
match (effective permission)
{
"action": "Microsoft.Resources/deployments/read",
"scope_type": "resource|resourceGroup|subscription"
}
where
at least one deployment in scope has output values carrying credential material
(listKeys() / listSecrets() results, or reference() Key Vault secret inline values)
output is NOT of secureString type (those are redacted in history)
emit
| source type | Identity |
|---|---|
| target type | Secret |
| source | <principal> |
| target | <secret / credential value in deployment output> |
| permissions | Microsoft.Resources/deployments/read |
| conditions | iam_permission |
| state logic | ACTIVE when the principal holds deployments/read AND the deployment output contains unredacted credential material (listKeys result, raw connection string, resolved Key Vault inline value written as a non-secure output type). CONDITIONAL(iam_permission) when deployment output content has not been confirmed to carry credentials — emit POTENTIAL(iam_permission) as a recon flag and upgrade to ACTIVE when evidence confirms credential-bearing outputs. BLOCKED if a deny assignment covers deployments/read. |
Narrative
{principal.name} holds deployments/read at {target.name}'s resource group scope and can retrieve the deployment output, which contains credential material (e.g. storage account keys from listKeys(), connection strings) - an indirect credential harvest without direct access to the downstream service.
Raw rule rules/derived/azure/arm-deployments.yaml
id: azure-arm-deployment-outputs-secret
emits: CanReadSecret
description: Principal with deployments/read can retrieve sensitive values (listKeys results, Key Vault
references) stored in deployment output history.
match_effective_permission:
action: Microsoft.Resources/deployments/read
scope_type: resource|resourceGroup|subscription
where:
- at least one deployment in scope has output values carrying credential material
- (listKeys() / listSecrets() results, or reference() Key Vault secret inline values)
- output is NOT of secureString type (those are redacted in history)
emit:
source_type: Identity
target_type: Secret
source: <principal>
target: <secret / credential value in deployment output>
permissions:
- Microsoft.Resources/deployments/read
conditions:
- iam_permission
state_logic: "ACTIVE when the principal holds deployments/read AND the deployment output contains unredacted\
\ credential material (listKeys result, raw connection string, resolved Key Vault inline value written\
\ as a non-secure output type). CONDITIONAL(iam_permission) when deployment output content has not\
\ been confirmed to carry credentials \u2014 emit POTENTIAL(iam_permission) as a recon flag and upgrade\
\ to ACTIVE when evidence confirms credential-bearing outputs. BLOCKED if a deny assignment covers\
\ deployments/read."
false_positive_note: "secureString and secureObject typed outputs/parameters ARE redacted in deployment\
\ history and the ARM API \u2014 do NOT emit CanReadSecret for those. Only `listKeys()` results, inline\
\ plaintext connection strings, Key Vault secret references whose value was materialized into a non-secure\
\ output, or raw storage account keys surface as readable. Collect and inspect the `properties.outputs`\
\ map before emitting ACTIVE \u2014 if outputs are absent or all typed secureString, do NOT emit.\
\ credential-chains.yaml read-secret-yields-identity collapses CanReadSecret + CredentialsFor(secret\
\ -> identity) into CanImpersonate \u2014 cite, do not re-derive."
narrative: "{principal.name} holds deployments/read at {target.name}'s resource group scope and can\
\ retrieve the deployment output, which contains credential material (e.g. storage account keys from\
\ listKeys(), connection strings) \u2014 an indirect credential harvest without direct access to the\
\ downstream service."
derived_from:
- <deployments/read effective permission>
- "credential-chains.yaml: read-secret-yields-identity (CanReadSecret + CredentialsFor => CanImpersonate\
\ \u2014 cited)"