Microsoft Defender for Cloud · Automation
Automation account variables should be encrypted
Written and reviewed by Emnode · Last reviewed
What does the recommendation "Automation account variables should be encrypted" check?
Flags any Automation account variable asset whose 'isEncrypted' property is false, meaning its value is stored and returned in plaintext rather than sealed with the account's unique encryption key, which Azure holds in a system-managed Key Vault. It inspects each variable individually, so one unencrypted variable trips the control even if every other variable in the account is encrypted. It does not look at the value itself, so it cannot tell whether a plaintext variable actually holds a secret, and it does not cover Automation credentials, certificates or connections, which are encrypted by default and assessed separately. The recommendation is audit-only: it surfaces the finding but never changes a variable for you.
Why does "Automation account variables should be encrypted" matter?
Teams routinely park connection strings, API keys, webhook URLs and tenant identifiers in Automation variables to share them across runbooks. An unencrypted variable returns its value in plaintext to anyone who can read it through the portal, the REST API or 'Get-AzAutomationVariable', so the secret is exposed to every operator with Reader on the account rather than only to the runbook that needs it. That widens the blast radius of a single over-permissioned role assignment or a leaked management credential, and the plaintext value can surface in API responses, exports and audit captures. Encrypting the variable means the value can only be retrieved from inside a runbook or DSC configuration, never read back externally.
How do I fix "Automation account variables should be encrypted"?
- Encryption can only be set when a variable is created, so identify each unencrypted variable, recreate it as encrypted, then delete the old one. In PowerShell: 'New-AzAutomationVariable -ResourceGroupName <rg> -AutomationAccountName <acct> -Name <name> -Value <value> -Encrypted $true', then 'Remove-AzAutomationVariable' for the plaintext original.
- In Bicep or ARM, set 'isEncrypted: true' on each 'Microsoft.Automation/automationAccounts/variables' resource so redeployments never reintroduce a plaintext variable.
- Assign the built-in audit policy at your management group or subscription scope to catch any new plaintext variable. Look the definition up by name rather than hardcoding a GUID: pid=$(az policy definition list --query "[?displayName=='Automation account variables should be encrypted'].name" -o tsv); az policy assignment create --name encrypt-automation-vars --policy "$pid" --scope <scope>.
Remediation script · bash
# Recreate a sensitive plain-text variable as an encrypted secure asset (PowerShell).
# Encryption is fixed at creation, so capture the value, then delete and recreate.
# az automation has no in-place toggle; the value can never be read back once encrypted.
pwsh -c '
$rg = "rg-automation"
$acct = "aa-operations"
$name = "SqlConnectionString"
$val = (Get-AzAutomationVariable -ResourceGroupName $rg `
-AutomationAccountName $acct -Name $name).Value
Remove-AzAutomationVariable -ResourceGroupName $rg `
-AutomationAccountName $acct -Name $name -Force
New-AzAutomationVariable -ResourceGroupName $rg `
-AutomationAccountName $acct -Name $name -Value $val -Encrypted $true
'
# Ratchet it shut: assign the built-in policy with a Deny effect so no new
# plain-text variable can be created. Look the definition up by display name,
# never paste a guessed GUID.
pid=$(az policy definition list \
--query "[?displayName=='Automation account variables should be encrypted'].name" -o tsv)
az policy assignment create \
--name deny-unencrypted-automation-vars \
--policy "$pid" \
--params '{"effect":{"value":"Deny"}}' \
--scope "/subscriptions/00000000-0000-0000-0000-000000000000" Full walkthrough (console steps, edge cases and verification) in the lesson Encrypt Azure automation and configuration data.
Is "Automation account variables should be encrypted" a false positive?
A variable that deliberately holds a non-sensitive operational value, such as a region code, a feature-flag boolean or an environment name used purely for runbook branching, still flags because the control checks the encryption flag, not the sensitivity of the content. Operators often leave these unencrypted on purpose so the value can be read back and confirmed from the portal, which an encrypted variable does not allow. If the value is genuinely public and you have confirmed it carries no secret, that finding is a safe, documented exception rather than a real exposure.