Skip to main content
Back to the Azure Footguns Database
GovernanceLowCommonAZF-0042

An orphaned NSG protects nothing and drifts into a misleading audit trail

A network security group associated with no subnet and no NIC enforces nothing, but its rules still show up in every review, quietly implying protection that isn't there.

Footgun ID
AZF-0042 (Azure Footgun No. 42)
Azure service
Azure Virtual Network
Resource type
Microsoft.Network/networkSecurityGroups
Updated
July 1, 2026

What it is

A network security group (NSG) whose subnets and networkInterfaces arrays are both empty. It has rules, but nothing is attached to it, so none of those rules apply to anything. It is a free resource, so it lingers in inventory indefinitely.

Impact (governance)
No direct charge; the cost is unmaintained rules and audit confusion
Basis: Azure behavior (authored assessment). Figures are estimates, not measurements.

Why it happens

NSGs are created and detached constantly during network churn: a subnet is re-architected, a NIC is deleted with its VM, an NSG is swapped for a newer one. Azure does not delete the old NSG, and since it carries no charge, nothing prompts a cleanup.

The trap is that an orphaned NSG still looks like a control. Its rules remain readable and editable, so someone can "harden" nsg-web-legacy believing they are tightening security, when the NSG governs zero resources. Over time these detached policies drift out of sync with the ones actually in force.

What it costs / blast radius

Nothing on the bill. The harm is security hygiene and governance: an orphaned NSG is dead configuration that misleads audits. Anyone reviewing your rule set has to work out which NSGs are live and which are decorative, and a change made to a detached NSG produces a false sense of protection. The more of them accumulate, the harder it is to reason about what your network actually allows. (Authored assessment of Azure behavior, not a measured statistic.)

See it

Find them: NSGs associated with no subnet and no NIC
Resources
| where type =~ 'microsoft.network/networkSecurityGroups'
| where array_length(coalesce(properties.subnets, dynamic([]))) == 0
    and array_length(coalesce(properties.networkInterfaces, dynamic([]))) == 0
| project name, resourceGroup, subscriptionId, location,
          ruleCount = array_length(properties.securityRules)
Fix: confirm no associations, then delete the detached NSG
// Both subnets and networkInterfaces empty means it protects nothing.
az network nsg show --name nsg-web-legacy --resource-group rg-net \
  --query "{subnets:subnets, nics:networkInterfaces}"
az network nsg delete --name nsg-web-legacy --resource-group rg-net

How StratoLens helps

StratoLens inventories every network security group across every subscription in your own tenant and flags the ones associated with nothing, so detached policies stop masquerading as active controls. Continuously and automatically, which keeps your live rule set legible when it matters for an audit.

Start Your 28-Day Free Trial

Every feature unlocked. Deploys to your Azure tenant. No data leaves your tenant.

Available now on the Azure Marketplace.

Built for Azure infrastructure teams who need complete visibility across their entire estate.