Back to blog
AzureBest PracticesCloud SecurityCompute & ContainersOperations & Compliance

Azure VM OS Disk Not Encrypted: Why It Matters and How to Fix It

Learn why an unencrypted Azure VM OS disk is a risk and how to fix it with encryption at host, CMK, or Azure Disk Encryption, plus policy-as-code prevention.

TL;DR

This check flags Azure VMs whose OS disk has no encryption at rest. Anyone who gets hold of the underlying disk artifacts could read your data in the clear. Fix it by enabling Azure Disk Encryption or confirming your disks use a customer-managed key, and enforce platform-managed encryption by default.

Every managed disk in Azure is supposed to be encrypted at rest. In practice, the picture is more nuanced than "encrypted yes or no." Azure offers several layers, and a VM can technically have a disk that falls outside your encryption requirements, whether that is because Azure Disk Encryption was never enabled, the disk predates a policy change, or someone created it from an unencrypted source. This Lensix check, vm_osdiskencryption, looks at the OS disk attached to a VM and tells you when encryption at rest is not enabled to the standard you expect.

The OS disk is worth singling out. It holds the operating system, cached credentials, paging files, application binaries, and very often local configuration that includes secrets. If that disk is readable by someone it should not be, the blast radius is the whole machine.


What this check detects

The check inspects the OS disk of each Azure virtual machine and reports a finding when encryption at rest is not enabled. There are a few distinct encryption mechanisms in Azure, and it helps to know which one you are dealing with:

  • Server-side encryption (SSE) with platform-managed keys (PMK): On by default for managed disks. Azure manages the keys for you.
  • Server-side encryption with customer-managed keys (CMK): SSE, but the key lives in your Azure Key Vault, so you control rotation and revocation.
  • Azure Disk Encryption (ADE): Uses BitLocker (Windows) or DM-Crypt (Linux) inside the guest OS to encrypt the volume itself.
  • Encryption at host: Encrypts data on the VM host, covering OS disk, data disks, and temp disk, with no performance hit from in-guest encryption.

A finding from this check typically means the OS disk is not covered by the encryption mechanism your organization requires, most commonly ADE not being enabled, or a disk that is not associated with a disk encryption set when CMK is mandated.

Note: Azure managed disks have had SSE with platform-managed keys enabled by default since 2017, and you cannot turn it off. So "not encrypted" in this context usually means "not encrypted to the level your policy demands," not "stored in plaintext on bare metal." That distinction matters when you triage findings.


Why it matters

Encryption at rest protects against a specific class of threats: someone reading data from storage they should not have logical access to. A few concrete scenarios where it earns its keep:

  • Stolen or copied disk artifacts. If an attacker gains access to your storage layer, snapshot exports, or a misconfigured blob, an unencrypted disk image can be mounted and read offline. With CMK or ADE, the data is useless without the key.
  • Snapshot and export leakage. Disk snapshots inherit a lot, but a snapshot of an unencrypted disk is an unencrypted snapshot. People share snapshots across subscriptions and regions far too casually. CMK lets you revoke access by disabling the key.
  • Compliance failures. PCI DSS, HIPAA, ISO 27001, and SOC 2 all expect demonstrable encryption at rest, frequently with customer control over keys. Default PMK passes some audits and fails others, depending on the auditor and the data class.
  • Insider risk and key revocation. With customer-managed keys you can cut off access instantly during an incident by disabling or deleting the key. Platform-managed keys give you no such lever.

The business case comes down to control. If you cannot prove who can decrypt the OS disk and how you would revoke that ability, you do not really control the data on it.

Warning: Azure Disk Encryption on the OS disk requires a reboot and, for some VM sizes and OS images, is not supported at all. Plan the change during a maintenance window and confirm support for your VM size and OS before you start.


How to fix it

The right fix depends on which standard you are trying to meet. Two common goals: enable in-guest encryption with Azure Disk Encryption, or move the disk to server-side encryption with a customer-managed key. Pick one based on your compliance requirement, and prefer encryption at host where it fits, since it is the simplest to operate.

Option 1: Enable encryption at host (recommended for most cases)

Encryption at host covers the OS disk, data disks, and temp disk with no in-guest agent and no BitLocker or DM-Crypt overhead. First register the feature on the subscription if you have not already:

az feature register --namespace Microsoft.Compute --name EncryptionAtHost

# Wait until "Registered", then propagate
az provider register --namespace Microsoft.Compute

Danger: Enabling encryption at host on an existing VM requires it to be deallocated first. That means downtime. Do not run this against a running production VM without a maintenance window and a tested rollback plan.

# Stop and deallocate the VM
az vm deallocate --resource-group myRG --name myVM

# Enable encryption at host
az vm update --resource-group myRG --name myVM --set securityProfile.encryptionAtHost=true

# Start it back up
az vm start --resource-group myRG --name myVM

Option 2: Server-side encryption with a customer-managed key

If your requirement is customer-controlled keys, create a Key Vault key, a disk encryption set, and associate the disk with it.

# Create a Key Vault with purge protection (required for disk encryption sets)
az keyvault create \
  --name myDiskVault \
  --resource-group myRG \
  --location eastus \
  --enable-purge-protection true

# Create a key
az keyvault key create --vault-name myDiskVault --name myDiskKey --protection software

# Create a disk encryption set
keyId=$(az keyvault key show --vault-name myDiskVault --name myDiskKey --query key.kid -o tsv)

az disk-encryption-set create \
  --resource-group myRG \
  --name myDiskEncSet \
  --key-url "$keyId" \
  --source-vault myDiskVault

# Grant the disk encryption set's identity access to the vault
desIdentity=$(az disk-encryption-set show --name myDiskEncSet --resource-group myRG --query identity.principalId -o tsv)

az keyvault set-policy \
  --name myDiskVault \
  --object-id "$desIdentity" \
  --key-permissions get wrapKey unwrapKey

To apply CMK to an existing OS disk, deallocate the VM, then update the disk's encryption settings:

az vm deallocate --resource-group myRG --name myVM

desId=$(az disk-encryption-set show --name myDiskEncSet --resource-group myRG --query id -o tsv)

az disk update \
  --resource-group myRG \
  --name myVM_OsDisk \
  --encryption-type EncryptionAtRestWithCustomerKey \
  --disk-encryption-set "$desId"

az vm start --resource-group myRG --name myVM

Option 3: Azure Disk Encryption (in-guest)

If your standard specifically calls for guest-level encryption with BitLocker or DM-Crypt:

az vm encryption enable \
  --resource-group myRG \
  --name myVM \
  --disk-encryption-keyvault myDiskVault \
  --volume-type OS

# Verify status
az vm encryption show --resource-group myRG --name myVM

Tip: For new VMs, set encryption at the point of creation so you never deal with deallocation downtime. Pass --encryption-at-host true on az vm create, or reference a disk encryption set in your image and disk definitions from day one.


How to verify the fix

Confirm the OS disk now reports the encryption type you intended:

az vm show --resource-group myRG --name myVM \
  --query "storageProfile.osDisk.managedDisk.id" -o tsv

az disk show --ids <disk-id> \
  --query "{name:name, encryptionType:encryption.type, des:encryption.diskEncryptionSetId}" -o json

For encryption at host, check the VM's security profile:

az vm show --resource-group myRG --name myVM \
  --query "securityProfile.encryptionAtHost" -o tsv

How to prevent it from happening again

Manual remediation does not scale. Bake encryption into your provisioning and block non-compliant resources before they exist.

Azure Policy

Use built-in policies to audit or deny disks that lack the encryption type you require. Assign the policy that requires disk encryption sets for managed disks, or the encryption-at-host policy, at the subscription or management group level:

# Example: assign the built-in policy requiring encryption at host
az policy assignment create \
  --name "require-encryption-at-host" \
  --scope "/subscriptions/<sub-id>" \
  --policy "fc4d8e41-e223-45ea-9bf5-eada37891d87" \
  --params '{"effect": {"value": "Deny"}}'

Note: Start any new policy in Audit mode, not Deny. Run it for a sprint, review what it would have blocked, then flip to Deny once you are confident it will not break legitimate deployments.

Terraform with encryption by default

Make the secure path the default in your modules so engineers cannot forget:

resource "azurerm_disk_encryption_set" "main" {
  name                = "des-platform"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  key_vault_key_id    = azurerm_key_vault_key.disk.id

  identity {
    type = "SystemAssigned"
  }
}

resource "azurerm_linux_virtual_machine" "main" {
  name                = "vm-app-01"
  resource_group_name = azurerm_resource_group.main.name
  # ... other config ...

  encryption_at_host_enabled = true

  os_disk {
    caching                = "ReadWrite"
    storage_account_type   = "Premium_LRS"
    disk_encryption_set_id = azurerm_disk_encryption_set.main.id
  }
}

CI/CD gates

Run static analysis on your IaC before it merges. Tools like Checkov or tfsec catch missing encryption settings in pull requests, well before anything reaches Azure:

# Fail the pipeline on Azure disk encryption violations
checkov -d ./terraform --framework terraform \
  --check CKV_AZURE_50,CKV_AZURE_93

Tip: Pair the policy-as-code gate with continuous monitoring in Lensix. Pipeline scans catch new code, and the vm_osdiskencryption check catches drift, manual changes, and resources created outside your pipelines.


Best practices

  • Decide your standard once. Pick whether your baseline is PMK, CMK, or encryption at host based on your compliance obligations, then apply it uniformly. Mixed encryption strategies across a fleet are hard to audit.
  • Prefer encryption at host for new workloads. It covers OS, data, and temp disks, has no in-guest performance penalty, and avoids the reboot churn of ADE.
  • Use customer-managed keys for regulated data. The ability to revoke decryption by disabling a key is a meaningful incident response control.
  • Enable purge protection and soft delete on the Key Vault. Disk encryption sets require it, and it prevents an accidental key deletion from permanently locking you out of every disk that depends on it.
  • Rotate keys on a schedule. With CMK you own rotation. Automate it and confirm disks pick up the new key version.
  • Encrypt data disks and snapshots too. The OS disk is the priority for this check, but the same threat model applies to attached data disks and any snapshots you create. Apply the same encryption set to all of them.

Encryption at rest is one of the cheapest, highest-leverage controls in Azure. The default platform-managed encryption gives you a floor, but for anything sensitive you want the control that CMK and encryption at host provide. Fix the existing findings, then make the secure configuration the default so the problem stops recurring.