Azure Storage Account Security Analyzer

Check an Azure storage account against the settings that decide who reaches it: shared key access, which makes the rest advisory, public blob access, the network default action, and the soft delete that covers deletion but not overwrites.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Check the account. Nothing leaves this tab.

Wanted a different tool?

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

An account with nothing set

Every property is absent, and absent is the old permissive default rather than a safe one: shared key on, public blob access on, TLS 1.0

{"name":"legacystorage","properties":{}}

A private endpoint that closed nothing

Virtual network rules beside a default action of Allow are decoration, because the public path is still open

{"name":"prodstorage","properties":{"allowSharedKeyAccess":false,"allowBlobPublicAccess":false,"minimumTlsVersion":"TLS1_2","networkAcls":{"defaultAction":"Allow","ipRules":[],"virtualNetworkRules":[{"id":"/subscriptions/x/subnets/app"}]}}}

Soft delete on, versioning off

Soft delete covers a delete and not an overwrite, which is the shape of most accidental data loss

{"name":"prodstorage","properties":{"allowSharedKeyAccess":false,"allowBlobPublicAccess":false,"minimumTlsVersion":"TLS1_2","allowCrossTenantReplication":false,"networkAcls":{"defaultAction":"Deny"},"deleteRetentionPolicy":{"enabled":true,"days":7},"containerDeleteRetentionPolicy":{"enabled":true,"days":7}}}

A retention policy that is switched off

enabled:false with a days value looks like protection in a diff and is none, so the finding is the same as having no policy at all

{"name":"prodstorage","properties":{"allowSharedKeyAccess":false,"allowBlobPublicAccess":false,"minimumTlsVersion":"TLS1_2","networkAcls":{"defaultAction":"Deny"},"deleteRetentionPolicy":{"enabled":false,"days":30}}}

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Hardening a storage account with shared key access left on

    While the account key works, holding it is full control of every container, blob, queue and table, with no per-identity audit: the activity log records the account rather than the person. RBAC, conditional access and private endpoints all describe a path the key does not take.

    Instead:Set allowSharedKeyAccess to false and move clients to Entra ID. Replace SAS signed with the account key first, because those stop working.

  2. Setting a container to private and expecting the account to follow

    It works the other way round. `allowBlobPublicAccess` on the ACCOUNT decides whether a container's public setting is honoured at all, and it defaults to enabled on any account created before the property existed.

    Instead:Set allowBlobPublicAccess to false at the account. Tell the container owners, because they will see their own setting unchanged and conclude nothing applied.

  3. Reading an absent property as a safe default

    Several of these were added after storage accounts existed, and absent means the behaviour from before, which is the permissive one. An old account reports TLS 1.0 as its minimum and shared key as enabled, and nobody chose either.

    Instead:Set them explicitly on every account rather than relying on what a newly created one gets.

  4. Adding a private endpoint and leaving networkAcls at Allow

    A private endpoint adds a route, it does not remove the public one. The account is then reachable both ways and the virtual network rules beside it are decoration.

    Instead:Set defaultAction to Deny, then allow what needs in. Keep the trusted Microsoft services bypass, or backup and diagnostics stop working.

  5. Treating soft delete as a backup

    It covers deletion and nothing else. Overwriting a blob with new content is not a deletion, so the previous content is gone and soft delete never saw it. Deleting a container is a third case again, covered by neither unless container soft delete is on.

    Instead:Enable blob soft delete, container soft delete and versioning. They cover three different mistakes and you will make all three.

One switch makes every other control advisory

A storage account has a dozen security settings and they are not equal. While the account key works, most of the others describe a path the key does not take.

allowSharedKeyAccess is the one that matters

While it is true, anyone holding the account key has complete access to every container, blob, queue and table, and the activity log records the account rather than the person. RBAC assignments, conditional access and private endpoints all describe a different route. The key is also a single bearer secret that lives in application settings and in whatever copied them there, and it is what every SAS token is signed with.

az storage account update --name ACCOUNT \
  --allow-shared-key-access false

Every SAS signed with the account key stops working.
That is usually the thing to replace first.

The container's public setting is a request

allowBlobPublicAccess is the account-level control, and it either honours or ignores what a container asks for. With it false, a container marked public serves nothing, which is the correct direction and confuses the container's owner, who sees their own setting unchanged and concludes it did not apply. With it true, anyone who can configure a container can expose it.

Absent means the old permissive default

Several of these properties were added after storage accounts existed, and an account created before one has it absent. Absent is not neutral: it is the behaviour from before the property, which is the permissive one. So an old account reports TLS 1.0 as its minimum and shared key access as enabled, and nobody chose either.

A private endpoint does not close the public path

networkAcls.defaultAction defaults to Allow, meaning every network. Adding a private endpoint adds a second route rather than removing the first, so an account with both is reachable both ways and the virtual network rules alongside it are decoration. Setting defaultAction to Deny is the change that closes it, and it needs the trusted Microsoft services exception or backup and diagnostics stop working.

Soft delete covers deletion, and only deletion

Overwriting a blob with new content is not a deletion, so soft delete never sees it and the previous content is gone. That is the shape of most accidental data loss: a job writes an empty file over a good one. Versioning is what covers that, and it is separate. Deleting a container is a third case again, covered by neither unless container soft delete is on.

Cross-tenant replication is on by default

Anyone who can configure object replication can set a destination in a different Entra tenant. It is a supported feature and it is also a supported way for data to leave the organisation without leaving Azure. Turning it off is safe unless you genuinely replicate across tenants, which is rare and deliberate.

What this cannot see

It reads the account, so it does not know what is in it. It cannot see the containers and their individual public settings, the RBAC assignments and who holds them, the private endpoints attached, or the network rules' effect from where your clients actually are. Most importantly it cannot see any SAS already signed and circulating: those outlive every change made here, until either the key is rotated or the stored access policy behind them is revoked.