gcp-vpc-shared-vpc-network-reach
A service-project service account holding compute.networkUser on a host-project subnet can create workloads whose NICs land in that subnet, giving those workloads internal-IP reachability to all other resources in the subnet (including those from other service projects).
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
permission == compute.subnetworks.use (granted via roles/compute.networkUser on the subnet or host project)
?sa is a
ServiceAccount or Identity in a service project
?host_subnet is a Subnet in the host project (Shared VPC host)
emit
| source type | Identity |
|---|---|
| target type | Network |
| source | ?sa |
| target | <VMs / resources co-located in ?host_subnet> |
| permissions | compute.subnetworks.use compute.instances.create iam.serviceAccounts.actAs |
| conditions | network_reachability iam_permission |
| state logic | CONDITIONAL(iam_permission) — requires compute.subnetworks.use on the host subnet AND compute.instances.create + iam.serviceAccounts.actAs to materialize a workload in the subnet. CONDITIONAL(network_reachability) applies to the resulting VM's lateral reach within the subnet after the workload is created. |
Narrative
Service account {sa.name} holds compute.subnetworks.use on Shared VPC subnet {subnet.name} in host project {host_project.name}. Creating a workload in this subnet places it in the same network segment as all other service-project workloads sharing that subnet, enabling internal-IP reachability to those resources.
Raw rule rules/derived/gcp/vpc.yaml
id: gcp-vpc-shared-vpc-network-reach
emits: CanNetworkReach
description: A service-project service account holding compute.networkUser on a host-project subnet can
create workloads whose NICs land in that subnet, giving those workloads internal-IP reachability to
all other resources in the subnet (including those from other service projects).
applies_to:
- gcp
match:
- - sa: null
- HasPermission
- host_subnet: null
where:
- permission == compute.subnetworks.use (granted via roles/compute.networkUser on the subnet or host project)
- ?sa is a ServiceAccount or Identity in a service project
- ?host_subnet is a Subnet in the host project (Shared VPC host)
emit:
source_type: Identity
target_type: Network
source: ?sa
target: <VMs / resources co-located in ?host_subnet>
permissions:
- compute.subnetworks.use
- compute.instances.create
- iam.serviceAccounts.actAs
conditions:
- network_reachability
- iam_permission
state_logic: "CONDITIONAL(iam_permission) \u2014 requires compute.subnetworks.use on the host subnet\
\ AND compute.instances.create + iam.serviceAccounts.actAs to materialize a workload in the subnet.\
\ CONDITIONAL(network_reachability) applies to the resulting VM's lateral reach within the subnet\
\ after the workload is created."
confidence: '0.80'
derived_from:
- "<CrossProjectTrust: service_project \u2192 host_project>"
- '<HasPermission: ?sa compute.subnetworks.use on ?host_subnet>'
false_positive_note: (1) compute.subnetworks.use alone does not create network reachability; the SA
must also be able to create (or already have) a compute instance in the subnet (compute.instances.create
+ iam.serviceAccounts.actAs). If only subnetworks.use is held, downgrade to POTENTIAL(iam_permission).
(2) Firewall rules in the host project apply to all tenant workloads in the subnet. A deny-all-intra-subnet
rule would block lateral movement even within the same subnet. (3) Shared VPC subnets from different
regions are NOT in the same L2 domain; region matters for direct L3 adjacency.
narrative: Service account {sa.name} holds compute.subnetworks.use on Shared VPC subnet {subnet.name}
in host project {host_project.name}. Creating a workload in this subnet places it in the same network
segment as all other service-project workloads sharing that subnet, enabling internal-IP reachability
to those resources.