AllowVnetInBound Quietly Flattens Your Subnet Boundaries
An Azure subnet layout looks segmented on a diagram, but every NSG ships with a rule permitting all traffic sourced from the VirtualNetwork tag. A single compromised host can traverse peered VNets and hub-spoke topologies unimpeded, because the segmentation implied by subnet CIDRs was never actually enforced at the NSG layer.
At a glance
- Unsafe setting
- NSGs rely on the unmodified default AllowVnetInBound rule at priority 65000 for internal traffic control.
- Failure trigger
- A host in one subnet or peered VNet is compromised and initiates lateral connections that the VirtualNetwork tag permits by default.
- Blast radius
- Compromise in a low-value subnet or peered spoke propagates unimpeded into production tiers because internal traffic was never explicitly denied.
- Recommended control
- Insert explicit ASG-scoped deny rules below priority 65000 and route inter-spoke traffic through an inspected hub firewall rather than flat peering.
The Trap
The default NSG inbound rule AllowVnetInBound, sitting at priority 65000 on every Network Security Group in Azure, permits any traffic whose source matches the VirtualNetwork service tag. That tag does not mean “this subnet” or even “this VNet” — it resolves to every address space reachable through VNet peering, VPN gateways, and ExpressRoute circuits attached to the virtual network, including transitively peered spokes in a hub-and-spoke design.
The Default State
Every NSG created in Azure, whether attached to a subnet or a NIC, comes with three immutable default rules: AllowVnetInBound (65000), AllowAzureLoadBalancerInBound (65001), and DenyAllInBound (65500). Engineers cannot delete these; they can only be overridden by rules with a lower priority number. Teams routinely build subnet-per-tier architectures — web, app, data — and assume the subnet boundary itself provides isolation, when in fact nothing is blocking east-west traffic between those tiers unless an explicit deny rule has been inserted above priority 65000.
The Blast Radius
A web tier host compromised via a public-facing application can reach the data tier over SMB, RDP, or the database port directly, because AllowVnetInBound has already granted that path before any custom rule is evaluated. In hub-spoke topologies the exposure compounds: a low-value dev/test spoke peered into the hub inherits reachability into production spokes through the VirtualNetwork tag’s transitive resolution, so a breach in a sandbox subscription becomes a lateral path into domain controllers or payment processing subnets several hops away. Because the rule is a platform default rather than an explicit configuration line, it rarely appears in change review, and vulnerability scanners checking “NSG attached: yes” report the subnet as protected when it is functionally open internally.
The Lead Mechanic Fix
Insert explicit deny rules below priority 65000 that scope traffic by Application Security Group rather than relying on the VirtualNetwork tag for anything other than genuinely trusted management planes:
az network nsg rule create –resource-group prod-net –nsg-name data-tier-nsg –name Deny-Lateral-Default –priority 200 –direction Inbound –access Deny –protocol ‘*’ –source-address-prefixes VirtualNetwork –destination-address-prefixes 10.20.2.0/24
Follow with narrow allow rules referencing ASGs for the specific app-tier hosts and ports permitted to reach the data tier. For hub-spoke estates, replace flat VNet peering with Azure Firewall or NVA-routed spokes and force all inter-spoke traffic through UDRs so it can be inspected, and audit every NSG with az network nsg rule list –nsg-name <nsg> –query “[?priority<65000]” to confirm a deny boundary actually exists before 65000 fires.