This check flags Azure Storage accounts where blob soft-delete is turned off, leaving you with no recovery window after an accidental or malicious delete. Enable it with az storage blob service-properties delete-policy update --enable true --days-retained 7.
Deleting a blob in Azure is permanent by default. There is no recycle bin, no undo, and no grace period. If an automation script targets the wrong container, an attacker wipes your data, or someone fat-fingers a cleanup job, the bytes are gone the moment the delete call returns. Blob soft-delete is the feature that turns that one-way door into a recoverable mistake, and this Lensix check catches every storage account where it is missing.
What this check detects
The storage_blobsoftdelete check inspects the blob service properties of each Azure Storage account in scope and reports any account where the soft-delete retention policy is disabled. When soft-delete is off, deleted blobs and their snapshots are removed immediately and cannot be restored through normal means.
Concretely, Lensix looks at the account's deleteRetentionPolicy setting on the blob service. If enabled is false (or the policy is unset), the account fails the check.
Note: Blob soft-delete is distinct from container soft-delete and from account-level deletion protection. Soft-delete for blobs recovers individual deleted blobs and overwritten blob versions. It does not recover a deleted container unless container soft-delete is also enabled. The two are separate toggles.
Why it matters
Storage accounts hold the data that everything else depends on: application assets, backups, logs, customer uploads, Terraform state, infrastructure artifacts. Losing that data is rarely recoverable from elsewhere, and the failure modes are more common than teams expect.
Accidental deletion
The most frequent cause of data loss is human error. A lifecycle script with a bad prefix filter, a misconfigured azcopy sync --delete-destination, or a developer running a cleanup against prod instead of dev can erase thousands of blobs in seconds. Without soft-delete, your only recourse is a separate backup, assuming one exists and is current.
Ransomware and malicious deletion
If an attacker gains access to a storage account key or a compromised identity with write permissions, deleting or overwriting your data is a common extortion tactic. Soft-delete gives you a recovery window even after a destructive action, buying time to detect the breach and restore from the retained copies.
Warning: Soft-delete is not a substitute for backups or an immutability policy. An attacker with sufficient permissions can wait out a short retention window or alter the policy itself. Treat soft-delete as a fast-recovery layer, not your last line of defense.
Overwrite recovery
Soft-delete also protects against accidental overwrites when blob versioning is enabled alongside it. A bad deploy that overwrites a config blob or static asset can be rolled back by restoring the previous version, instead of hunting for the old contents in a chat thread.
How to fix it
Enabling blob soft-delete is non-destructive and takes effect immediately. Pick a retention period that fits your recovery needs. Seven days is a sensible floor for most workloads, and 30 days is common for sensitive data.
Azure CLI
# Enable blob soft-delete with a 7-day retention window
az storage blob service-properties delete-policy update \
--account-name mystorageaccount \
--enable true \
--days-retained 7 \
--auth-mode login
Verify the change:
az storage blob service-properties delete-policy show \
--account-name mystorageaccount \
--auth-mode login \
--output json
You should see "enabled": true and the retention days you set.
Azure Portal
- Open the storage account in the Azure Portal.
- Under Data management, select Data protection.
- Check Enable soft delete for blobs.
- Set the retention period (in days).
- Click Save.
Tip: While you are on the Data protection screen, enable container soft-delete and blob versioning at the same time. Together they cover deleted blobs, deleted containers, and overwritten data, which closes most accidental-loss scenarios in one pass.
Terraform
resource "azurerm_storage_account" "example" {
name = "mystorageaccount"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "LRS"
blob_properties {
delete_retention_policy {
days = 7
}
container_delete_retention_policy {
days = 7
}
versioning_enabled = true
}
}
Bicep
resource blobService 'Microsoft.Storage/storageAccounts/blobServices@2023-01-01' = {
name: 'default'
parent: storageAccount
properties: {
deleteRetentionPolicy: {
enabled: true
days: 7
}
containerDeleteRetentionPolicy: {
enabled: true
days: 7
}
isVersioningEnabled: true
}
}
Warning: Longer retention windows increase storage cost because soft-deleted blobs are billed as if they still exist until they expire. For accounts with high churn or large objects, a 30-day window can add a noticeable line item. Right-size the retention period per account rather than applying one global maximum.
Restoring a soft-deleted blob
Once soft-delete is on, recovering a deleted blob is a single command. This is worth knowing before you need it under pressure.
az storage blob undelete \
--account-name mystorageaccount \
--container-name mycontainer \
--name path/to/blob.json \
--auth-mode login
To list blobs including soft-deleted ones so you can find what to restore:
az storage blob list \
--account-name mystorageaccount \
--container-name mycontainer \
--include d \
--auth-mode login \
--output table
How to prevent it from happening again
Fixing one account by hand does not stop the next account from being created without protection. Enforce the setting at provisioning time and audit it continuously.
Azure Policy
Azure ships a built-in audit policy for this. Assign it to flag any non-compliant accounts across a subscription or management group.
# Find the built-in policy definition
az policy definition list \
--query "[?contains(displayName, 'soft delete')].{name:name, displayName:displayName}" \
--output table
# Assign an audit policy at the subscription scope
az policy assignment create \
--name 'audit-blob-soft-delete' \
--display-name 'Audit storage accounts without blob soft-delete' \
--policy "<policy-definition-id>" \
--scope "/subscriptions/<subscription-id>"
Note: Azure Policy can audit existing accounts but it cannot retroactively enable soft-delete through a simple deployIfNotExists on the account resource alone, because the setting lives on the child blob service resource. Pair an audit policy with a remediation runbook or enforce the setting in your IaC modules so new accounts are born compliant.
CI/CD gate with policy-as-code
Catch the misconfiguration before it merges. A Checkov scan in your pipeline will fail any Terraform that defines a storage account without a delete retention policy.
# Scan Terraform in CI
checkov -d . --framework terraform \
--check CKV_AZURE_211,CKV2_AZURE_38
Wire this into your pull request workflow so a missing soft-delete policy blocks the merge instead of reaching production.
Tip: Bake soft-delete, container soft-delete, and versioning into a shared storage account module. When every team consumes the same module, the secure defaults come for free and nobody has to remember the flags.
Best practices
- Layer your protections. Enable blob soft-delete, container soft-delete, and blob versioning together. Each covers a different failure mode.
- Match retention to recovery objectives. Use longer windows for data you cannot recreate (backups, customer uploads) and shorter windows for high-churn, low-value data to control cost.
- Add immutability for critical data. For compliance or ransomware resilience, layer a time-based or legal-hold immutability policy on top of soft-delete so even an admin cannot delete protected blobs within the locked period.
- Lock down delete permissions. Soft-delete recovers data, but reducing who can delete in the first place is the better control. Scope RBAC so only the identities that need delete rights have them.
- Monitor delete operations. Send storage diagnostic logs to a Log Analytics workspace and alert on bulk delete activity, which is an early signal of both a runaway script and a malicious actor.
- Audit continuously. Drift happens. Accounts get recreated, modules get bypassed, manual changes slip through. Keep this check running so a regression surfaces in hours, not after an incident.
Danger: Disabling soft-delete on an account that already has soft-deleted blobs does not delete them immediately, but it stops protecting new deletes and removes your safety net. Never turn this off in production to silence a cost alert without first confirming you have backups and an immutability policy in place.
Blob soft-delete is one of the cheapest, lowest-risk safeguards you can apply to Azure Storage. It costs nothing to enable, it works retroactively for every future delete, and it has rescued more teams from a bad afternoon than they would ever admit. Turn it on everywhere, enforce it in code, and let Lensix tell you the moment an account slips out of compliance.

