This check flags Azure Blob containers configured for anonymous public access, which lets anyone on the internet read your objects without credentials. Disable public access at the storage account level with --allow-blob-public-access false and serve files through SAS tokens or a CDN instead.
Public blob containers are one of the most common causes of accidental data exposure in Azure. A single misconfigured container can put internal documents, backups, customer records, or application secrets a Google search away from anyone. This check catches containers that permit anonymous reads before someone else finds them first.
What this check detects
The storage_blobpublic check inspects your Azure Storage accounts and the Blob containers inside them for anonymous public access. In Azure, public access works on two levels:
- Account level: the
allowBlobPublicAccessproperty. When this istrue, individual containers are allowed to be made public. - Container level: the
publicAccesssetting, which can beNone,Blob, orContainer.
The two public values mean different things:
Blobgrants anonymous read access to the blobs themselves, but not to the container listing.Containergrants anonymous read access to the blobs and lets anyone enumerate every object in the container.
Note: A container can only be set to public if the parent storage account has allowBlobPublicAccess enabled. Turning that account-level flag off is the single most effective way to close this hole across every container at once.
The check fails when a container is set to Blob or Container access, or when the account has public access enabled and offers no guardrail against it.
Why it matters
Anonymous access removes authentication entirely. There is no IAM, no key, no SAS token, just an unauthenticated HTTPS GET. If an attacker can guess or discover the URL, they can read the data.
The real-world failure pattern usually looks like this:
- A developer sets a container to
Containeraccess to quickly share a few public assets. - Over time, the container becomes a dumping ground for other files: database exports, log archives, config files.
- Because the access mode allows listing, a scanner walks the entire container and pulls everything.
Attackers actively scan for this. Storage account URLs follow a predictable pattern (https://<account>.blob.core.windows.net/<container>), and tools exist purely to brute-force account and container names. A public container with listing enabled needs no guessing of individual blob names at all.
Danger: Public Container access is the worst case. It lets an anonymous user enumerate every blob, so one forgotten sensitive file in an otherwise public bucket exposes everything. Treat any container set to Container as an active incident until you confirm its contents are genuinely public data.
The business impact is concrete: exposed PII triggers breach notification obligations under GDPR, HIPAA, and similar regimes; exposed credentials lead to account takeover; and exposed backups hand attackers a full copy of your data with no logging that ties back to a compromised identity.
How to fix it
Start by finding out which accounts and containers are affected, then remediate.
1. Audit your storage accounts
List every storage account and its public access setting:
az storage account list \
--query "[].{name:name, group:resourceGroup, publicAccess:allowBlobPublicAccess}" \
--output table
For a specific account, list containers and their access level:
az storage container list \
--account-name mystorageaccount \
--auth-mode login \
--query "[].{name:name, publicAccess:properties.publicAccess}" \
--output table
2. Disable public access at the account level
This is the recommended fix. It blocks public access for all containers in the account in one operation:
az storage account update \
--name mystorageaccount \
--resource-group my-resource-group \
--allow-blob-public-access false
Warning: If any application legitimately serves public assets straight from this account (a static website, public images, downloads), flipping this flag will break those requests immediately. Confirm what each public container is used for before disabling, and plan to move genuinely public content behind a SAS token or CDN first.
3. Or set a single container back to private
If you need account-level public access to stay on for legitimate reasons, lock down the offending container individually:
az storage container set-permission \
--name leaky-container \
--account-name mystorageaccount \
--auth-mode login \
--public-access off
4. Fix it in the Azure Portal
- Open the storage account, then go to Settings > Configuration.
- Set Allow Blob anonymous access to Disabled and save.
- To handle a single container instead, go to Data storage > Containers, select the container, choose Change access level, and set it to Private (no anonymous access).
5. Serve public content the right way
If files genuinely need to be public, do not reach for anonymous access. Use a time-limited SAS token so access is scoped and revocable:
az storage blob generate-sas \
--account-name mystorageaccount \
--container-name assets \
--name logo.png \
--permissions r \
--expiry 2025-12-31T23:59:59Z \
--auth-mode login \
--as-user \
--full-uri
Tip: For high-traffic public assets, put Azure CDN or Front Door in front of a private container using a managed identity origin. You get caching, custom domains, and TLS without ever exposing the storage account directly.
How to prevent it from happening again
Manual fixes do not last. Anyone with Contributor rights can re-enable public access tomorrow. Enforce the rule at the platform level.
Azure Policy
Azure ships a built-in policy that denies storage accounts with public blob access. Assign it at the subscription or management group scope:
az policy assignment create \
--name deny-public-blob \
--display-name "Deny storage accounts with public blob access" \
--scope "/subscriptions/<subscription-id>" \
--policy "4733ea7b-a883-42fe-8cac-97454c2a9e4a" \
--params '{"effect": {"value": "Deny"}}'
With this in place, any attempt to create or update an account with public access set to enabled is rejected at deployment time.
Set the default in IaC
Bake the safe setting into your templates so new accounts are private by default. In Terraform:
resource "azurerm_storage_account" "main" {
name = "mystorageaccount"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
account_tier = "Standard"
account_replication_type = "LRS"
allow_nested_items_to_be_public = false
}
The allow_nested_items_to_be_public = false argument maps directly to the account-level flag and prevents any container in this account from going public.
Gate it in CI/CD
Catch the misconfiguration before it merges. Add a policy-as-code scan to your pipeline using a tool like Checkov against your Terraform plan:
checkov -d ./infra --check CKV_AZURE_59
Fail the build on any violation so a public account never reaches production in the first place.
Tip: Layer continuous detection on top of preventive controls. Lensix runs the storage_blobpublic check across all your subscriptions on a schedule, so a container that slips through (for example via a portal change outside your pipeline) gets flagged within minutes rather than at the next audit.
Best practices
- Default to private. Disable
allowBlobPublicAccesson every new account and only make exceptions with a documented reason. - Separate public from private data. Never mix sensitive files into a container that serves public content. Use a dedicated account for genuinely public assets so a mistake there cannot leak internal data.
- Prefer SAS tokens over anonymous access. Scoped, time-limited, revocable access beats wide-open reads every time.
- Use a stored access policy for SAS tokens so you can revoke them centrally without rotating account keys.
- Enable diagnostic logging. Turn on storage analytics and route logs to Log Analytics so you can see who is reading what. Anonymous reads will not have an identity, which makes monitoring even more important.
- Restrict network access. Combine private access with firewall rules or private endpoints so the account is only reachable from approved networks.
- Review access levels in code review. Any IaC change that sets a container to
BloborContainershould require explicit sign-off.
Public blob access is rarely needed and almost never worth the risk. Disable it by default, serve the genuine exceptions through SAS or a CDN, and enforce the rule with policy so the setting cannot drift back open.

