Microsoft Defender for Cloud · Azure Virtual Machines
Non-internet-facing virtual machines should be protected with network security groups
Written and reviewed by Emnode · Last reviewed
What does the recommendation "Non-internet-facing virtual machines should be protected with network security groups" check?
Flags virtual machines that have no internet exposure but whose subnet or network interface has no network security group attached, or whose attached NSG has an inbound rule allowing a source of 'Any' or 'Internet'. The check is about whether an NSG boundary exists around an internal VM, not about whether each individual rule is least-privilege. It does not cover internet-facing VMs, which are assessed separately as a High-severity recommendation, and it does not inspect Azure Firewall, route tables or third-party appliances, so a VM protected by those alone but with no NSG can still flag.
Why does "Non-internet-facing virtual machines should be protected with network security groups" matter?
Internal VMs are routinely treated as safe because they have no public IP, so teams leave their subnets wide open to lateral movement. That is exactly the path an attacker takes after a first foothold: one compromised host or a leaked credential, then unrestricted east-west traffic to the database tier, the domain controller or a build agent. An NSG on the subnet caps that blast radius, turning a single breach into a contained incident rather than a full environment takeover. The business consequence of skipping it is the difference between resetting one box and declaring a reportable data breach.
How do I fix "Non-internet-facing virtual machines should be protected with network security groups"?
- Associate a network security group with the VM's subnet so the rule set applies to every machine in it: az network vnet subnet update --resource-group <rg> --vnet-name <vnet> --name <subnet> --network-security-group <nsg>. Use --network-security-group on az network nic update only where you need per-interface granularity.
- Tighten the inbound rules so no rule uses a source of 'Any' or 'Internet'; scope sources to specific subnet CIDRs or application security groups, and group VMs with az network asg create so policy follows the workload rather than hard-coded IPs.
- Enforce the boundary going forward by assigning the built-in audit policy at runtime rather than pasting its GUID: pid=$(az policy definition list --query "[?displayName=='Non-internet-facing virtual machines should be protected with network security groups'].name" -o tsv); az policy assignment create --name nonpublic-vm-nsg --policy "$pid" --scope <scope>. The policy effect is AuditIfNotExists, so it reports gaps but does not create NSGs for you.
Remediation script · bash
# 1. Close the highest-impact exposure first: delete any rule that
# allows a management port from the whole internet.
for rule in $(az network nsg rule list -g prod-rg --nsg-name prod-nsg \
--query "[?access=='Allow' && (sourceAddressPrefix=='*' || sourceAddressPrefix=='Internet') && (destinationPortRange=='3389' || destinationPortRange=='22')].name" -o tsv); do
az network nsg rule delete -g prod-rg --nsg-name prod-nsg -n "$rule"
echo "$rule: open management-port rule removed"
done
# 2. Add an explicit deny on the management ports as a backstop.
az network nsg rule create -g prod-rg --nsg-name prod-nsg \
--name deny-mgmt-ports --priority 4000 --access Deny --direction Inbound \
--protocol Tcp --source-address-prefixes Internet \
--destination-port-ranges 22 3389
# 3. Gate the ports you still need behind just-in-time access.
# JIT is configured via PowerShell or the portal; request access with the CLI:
az security jit-policy list -o table # confirm the JIT policy is in place
# 4. Ratchet it shut: audit any VM left without an NSG (Defender built-in policy).
az policy assignment create \
--name audit-internet-facing-nsg \
--policy f6de0be7-9a8a-4b8a-b349-43cf02d22f7c \
--scope "/subscriptions/00000000-0000-0000-0000-000000000000" Full walkthrough (console steps, edge cases and verification) in the lesson Restrict virtual machine network exposure.
Is "Non-internet-facing virtual machines should be protected with network security groups" a false positive?
A VM deliberately placed in a subnet whose traffic is fully governed by Azure Firewall or a network virtual appliance, with NSGs intentionally omitted to avoid duplicated and conflicting rule sets, still flags because the control only recognises NSGs as the boundary. If that firewall-centric design is a reviewed decision, suppress the recommendation for those resources rather than bolting on a redundant NSG.