Assume Breach: Why Flat VNets and Permissive NSGs Fail When It Matters

Two common Azure network design choices that actively make compromise worse.

Most Azure environments aren’t breached because the firewall was missing.

They’re breached because once something failed, nothing slowed the attacker down.

Flat VNets and permissive NSGs feel productive. They reduce friction. They keep deployments moving.
But under an assume‑breach model, they don’t just fail to help — they actively make things worse.

This post reframes assume breach as a network design principle, then calls out two design choices that are incompatible with it.

The Mental Model

The common assumption

If everything is “internal”, broad connectivity is fine.

We can always tighten it later.
NSGs document intent.
Segmentation is something we add when security asks for it.

Why it breaks in the cloud

In Azure, compromise doesn’t arrive politely at the edge.

It arrives through:

  • leaked credentials
  • over‑permissioned workloads
  • compromised build agents
  • exposed management endpoints
  • misconfigured services

Once any internal workload is hostile, the question isn’t can it get in?
It’s how far can it go before anyone notices?

Flat networks and permissive rules answer that question very badly.

How It Really Works

Assume breach treats networking as a containment mechanism, not a convenience layer.

When a workload is compromised, the network should:

  • restrict what it can see
  • restrict what it can reach
  • restrict how quietly it can move

If the network does none of those things, it’s not neutral — it’s an accelerator.

Two common Azure patterns fail this test consistently.

Design Flaw #1: Flat VNets Justified by “It’s All Internal”

What this looks like

  • One large VNet
  • Multiple subnets by tier or function
  • NSGs with wide VirtualNetwork allows
  • East‑west traffic largely unrestricted

This is often defended as:

  • simpler
  • easier to operate
  • faster to deploy

Why it’s actively dangerous

Under assume breach, a flat VNet pre‑authorises lateral movement.

Once an attacker compromises:

  • a single VM
  • an app service with VNet integration
  • a container with network access

They inherit:

  • cheap reconnaissance
  • broad reachability
  • low‑noise scanning opportunities

The network doesn’t slow them down.
It helps them map your environment faster than you can respond.

This isn’t a theoretical risk. It’s how most real cloud incidents expand.

Design Flaw #2: NSGs Used as Documentation Instead of Enforcement

What this looks like

  • Large rule sets with “temporary” allows
  • Broad source prefixes “for flexibility”
  • Deny rules that technically exist but rarely trigger
  • Rules written to avoid breaking anything — ever

NSGs become a record of intent, not a constraint.

Why it’s actively dangerous

In a breach, ambiguity favours the attacker.

Permissive rules mean:

  • unclear blast radius
  • unpredictable access paths
  • difficulty reasoning under pressure

When incident response begins, teams often discover:

  • rules no one remembers adding
  • dependencies no one documented
  • access paths no one intended

At that point, tightening the network risks breaking production — so it doesn’t happen.

The attacker keeps moving.

Real‑World Impact

Design

You stop grouping resources by convenience and start grouping by what you’re willing to lose together.

If a subnet is compromised, what must still be unreachable?

Reliability

Containment prevents security incidents from becoming availability incidents.

A compromised workload shouldn’t be able to:

  • reach other workloads of the same tier
  • traverse management paths
  • interfere with recovery mechanisms

Security

Security posture improves after failure, not just before it.

That’s the difference between:

  • a design that looks secure on a diagram
  • a design that survives partial compromise

Cost

More segmentation costs something.

Unbounded lateral movement costs far more — usually measured in downtime, incident duration, and lost confidence rather than Azure spend.

Implementation Examples

Assume breach doesn’t require complex tooling.
It requires default denial and explicit intent.

Example: NSG as enforcement, not commentary

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
param location string = resourceGroup().location
param workloadsubnetresourcegroup string = 'rg-aue-networking'
param workloadvnetname string = 'vnet-workload'
param workloadsubnetname string = 'subnet-workload'
param nsgName string = 'nsg-workload'

resource workloadSubnet 'Microsoft.Network/virtualNetworks/subnets@2023-09-01' existing = {
  scope: resourceGroup(workloadsubnetresourcegroup)
  name: '${workloadvnetname}/${workloadsubnetname}'
  }

resource workloadSubnetNsg 'Microsoft.Network/networkSecurityGroups@2023-09-01' = {
  name: nsgName
  location: location
  properties: {
    securityRules: [
      {
        name: 'Allow-Explicit-Dependency'
        properties: {
          priority: 100
          direction: 'Outbound'
          access: 'Allow'
          protocol: 'Tcp'
          sourceAddressPrefix: '*'
          destinationAddressPrefix: workloadSubnet.properties.addressPrefix // dependency subnet
          destinationPortRange: '443'
        }
      }
      {
        name: 'Deny-East-West-Default'
        properties: {
          priority: 4096
          direction: 'Outbound'
          access: 'Deny'
          protocol: '*'
          sourceAddressPrefix: '*'
          destinationAddressPrefix: 'VirtualNetwork'
          destinationPortRange: '*'
        }
      }
    ]
  }
}

This doesn’t stop compromise.
It defines how far compromise can travel.

That’s the point.

Visualising the Difference

Flat, trust‑by‑default design

flowchart LR CompromisedWorkload --> SubnetA SubnetA --> SubnetB SubnetB --> SubnetC SubnetC --> Data

Movement is easy, fast, and quiet.

Assume‑breach‑oriented design

flowchart LR CompromisedWorkload --> SubnetA SubnetA -.blocked.- SubnetB SubnetA --> ExplicitDependency

The attacker hits friction immediately.

Gotchas & Edge Cases

  • Over‑segmentation can hurt operability
    If engineers can’t diagnose issues during an incident, the design has overshot.

  • Platform traffic still needs consideration
    Health probes, control plane access, and managed service behaviour must be explicitly allowed — not assumed.

  • NSGs are not policy engines
    Keep rules few, intentional, and aggressively pruned.

Best Practices

  • Treat “internal” as a routing concept, not a trust guarantee
  • Design subnets around failure domains, not org charts
  • Default to east‑west deny, then add explicit intent
  • Regularly delete rules you can’t justify under breach
  • Revisit network boundaries after incidents — not just audits
🍺
Brewed Insight:

Flat networks and permissive NSGs don’t just fail under breach — they make compromise faster, quieter, and harder to contain.

If your network can’t limit damage after something goes wrong, it’s not defensive architecture. It’s optimism.

Learn More