azure-vnet-cross-sub-peering

A Connected VNet peering that crosses Azure subscriptions (emitted from explicit azure-vnet-peering-record) extends network reachability AND establishes a cross-subscription trust boundary - a critical lateral-movement fact.

derived azure emits PeeredWithCrossAccountTrust

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'localVNet': None} PeeredWith {'remoteVNet': None}

where

?localVNet.subscription_id != ?remoteVNet.subscription_id (subscription boundary crossed) ?localVNet.tenant_id == ?remoteVNet.tenant_id (same tenant; for cross-tenant see azure-vnet-cross-tenant-peering) peeringState == Connected on both sides (from explicit record)

emit

Raw rule rules/derived/azure/vnet.yaml

id: azure-vnet-cross-sub-peering
emits:
- PeeredWith
- CrossAccountTrust
description: "A Connected VNet peering that crosses Azure subscriptions (emitted from explicit azure-vnet-peering-record)\
  \ extends network reachability AND establishes a cross-subscription trust boundary \u2014 a critical\
  \ lateral-movement fact."
match:
- - localVNet: null
  - PeeredWith
  - remoteVNet: null
where:
- ?localVNet.subscription_id != ?remoteVNet.subscription_id (subscription boundary crossed)
- ?localVNet.tenant_id == ?remoteVNet.tenant_id (same tenant; for cross-tenant see azure-vnet-cross-tenant-peering)
- peeringState == Connected on both sides (from explicit record)
emit:
- edge_type: PeeredWith
  source_type: VirtualNetwork
  target_type: VirtualNetwork
  source: <local VNet node>
  target: <remote VNet node, peered across the subscription boundary>
  permissions: []
  state_logic: ACTIVE when peeringState is Connected on both sides. CONDITIONAL(network_reachability)
    if remote-side state is unconfirmed (collection gap on remote subscription).
  derived_from:
  - azure-vnet-peering-record
- edge_type: CrossAccountTrust
  source_type: Account
  target_type: Account
  source: <Subscription node (Account class) containing local VNet>
  target: <Subscription node (Account class) containing remote VNet>
  permissions: []
  properties:
    cross_subscription: true
    local_subscription: '{localVNet.subscription_id}'
    remote_subscription: '{remoteVNet.subscription_id}'
  state_logic: ACTIVE when peeringState is Connected on both sides and subscription mismatch is confirmed.
    CONDITIONAL(network_reachability) if remote-side state is unconfirmed (collection gap on remote subscription).
  derived_from:
  - azure-vnet-peering-record
  false_positive_note: "This rule emits TWO edges: (1) PeeredWith (network-layer reachability, already\
    \ in explicit), (2) CrossAccountTrust (subscription boundary crossing). ARM control does not cross\
    \ subscription boundaries via peering. An attacker with a foothold in the remote subscription's VNet\
    \ gains network-layer reach into this VNet subject to NSG rules. Peering is non-transitive \u2014\
    \ do not chain these edges."
  narrative: VNet {localVNet.name} (subscription {source.id}) is peered with VNet {remoteVNet.name} (subscription
    {target.id}); a foothold in that subscription grants network-layer reach across the account boundary.
move · open · esc close