Skip to main content
emnode
Compliance Medium severity MCSB NS-2

Microsoft Defender for Cloud · Azure Storage

Storage accounts should restrict network access using virtual network rules

Written and reviewed by Emnode · Last reviewed

What does the recommendation "Storage accounts should restrict network access using virtual network rules" check?

Flags storage accounts whose firewall default action is still 'Allow', meaning the account accepts connections from any network rather than only from approved virtual network subnets. It is satisfied once 'networkRuleSet.defaultAction' is 'Deny' and at least one virtual network rule is present. It deliberately favours virtual network rules over IP allow-lists, since public IPs are a weaker boundary. Note the scope is narrow: the built-in policy only confirms that a VNet rule exists. It does NOT verify that 'publicNetworkAccess' is disabled, that private endpoints are in place, or that the listed subnets are the correct ones, so an account locked down purely through private endpoints can still appear non-compliant.

Why does "Storage accounts should restrict network access using virtual network rules" matter?

A storage account left open to all networks is reachable from any internet client that holds a key, SAS token or valid Entra credential, so a single leaked secret turns into data exfiltration with no network barrier to slow it down. Restricting access to named virtual network subnets means a stolen credential is useless unless the attacker is also inside your network perimeter. The business consequence of skipping this is a breach that bypasses your entire private network investment: the data plane stays exposed even while everything around it is firewalled. Virtual network rules also pair naturally with service endpoints, so traffic from an approved subnet reaches Storage over the Azure backbone rather than the public internet, keeping both the access boundary and the transit path inside your control.

How do I fix "Storage accounts should restrict network access using virtual network rules"?

  1. Enable the Microsoft.Storage service endpoint on each subnet that needs access: 'az network vnet subnet update --resource-group <rg> --vnet-name <vnet> --name <subnet> --service-endpoints Microsoft.Storage'.
  2. Add a virtual network rule binding that subnet to the account: 'az storage account network-rule add --resource-group <rg> --account-name <name> --vnet-name <vnet> --subnet <subnet>'.
  3. Flip the firewall default to deny while keeping trusted platform services working: 'az storage account update --resource-group <rg> --name <name> --default-action Deny --bypass AzureServices'. In Bicep, set 'networkAcls.defaultAction: 'Deny'' with a populated 'virtualNetworkRules' array. To enforce at scale, assign the built-in policy by display name: pid=$(az policy definition list --query "[?displayName=='Storage accounts should restrict network access using virtual network rules'].name" -o tsv); az policy assignment create --name restrict-storage-net --policy "$pid" --scope <scope>.

Remediation script · bash

# Close the highest-impact storage exposure first: anonymous read AND plain HTTP.
for acct in $(az storage account list \
    --query "[?allowBlobPublicAccess].name" -o tsv); do
  az storage account update --name "$acct" \
    --allow-blob-public-access false \
    --https-only true \
    --min-tls-version TLS1_2
  echo "$acct: anonymous access disabled, secure transfer required, min TLS 1.2"
done

# Ratchet it shut: deny any future account that allows anonymous access.
az policy assignment create \
  --name deny-anon-blob \
  --policy 13e6c4f1-e83f-4b50-a677-2cf6e2b9c885 \
  --scope "/subscriptions/00000000-0000-0000-0000-000000000000"

Full walkthrough (console steps, edge cases and verification) in the lesson Harden Azure Storage accounts.

Is "Storage accounts should restrict network access using virtual network rules" a false positive?

An account fully isolated with a private endpoint and 'publicNetworkAccess' set to 'Disabled', and therefore with no virtual network rules at all, still flags. The built-in policy only looks for a VNet rule in the rule set, so the stronger private-endpoint design reads as non-compliant. This is the documented behaviour, not a defect: confirm the private endpoint and disabled public access are correct, then exempt the resource rather than weakening it to add a redundant VNet rule.