gcp-ncc-spoke-update-accept-pending
A principal with effective networkconnectivity.spokes.update on the hub project can accept PENDING_REVIEW spokes that are awaiting hub approval. If an attacker has created a pending spoke attaching their VPC to the hub, a compromised hub-project identity can immediately accept it, placing the attacker's network on the routing fabric without requiring hub owner approval.
match (effective permission)
where
emit
| source type | Identity |
|---|---|
| target type | TransitGateway |
| source | <principal> |
| target | <NCC Hub (TransitGateway) node> |
| permissions | networkconnectivity.spokes.update |
| conditions | iam_permission service_state |
| state logic | CONDITIONAL(service_state) because at least one PENDING_REVIEW spoke must exist on the hub to exercise this capability. ACTIVE if a PENDING_REVIEW spoke exists and ?principal holds networkconnectivity .spokes.update (effective). CONDITIONAL(iam_permission) if the effective-permission evaluator cannot confirm the permission. |
Narrative
{principal.name} holds networkconnectivity.spokes.update on hub project {hub_project.name} and can accept PENDING_REVIEW spokes on NCC Hub {hub.name}. An attacker who has created a pending spoke attaching their VPC to {hub.name} would be immediately approved, placing the attacker's network on the hub's routing fabric and opening routing to all other spoke-attached VPCs - a direct bypass of hub owner approval.
Raw rule rules/derived/gcp/ncc.yaml
id: gcp-ncc-spoke-update-accept-pending
emits: CanModifyConfiguration
description: A principal with effective networkconnectivity.spokes.update on the hub project can accept
PENDING_REVIEW spokes that are awaiting hub approval. If an attacker has created a pending spoke attaching
their VPC to the hub, a compromised hub-project identity can immediately accept it, placing the attacker's
network on the routing fabric without requiring hub owner approval.
applies_to:
- gcp
match_effective_permission:
action: networkconnectivity.spokes.update
resource_type: networkconnectivity.googleapis.com/Hub
where:
- 'at_least_one_pending_spoke_exists_on_hub: true (PENDING_REVIEW spoke exists)'
emit:
source_type: Identity
target_type: TransitGateway
source: <principal>
target: <NCC Hub (TransitGateway) node>
permissions:
- networkconnectivity.spokes.update
conditions:
- iam_permission
- service_state
state_logic: CONDITIONAL(service_state) because at least one PENDING_REVIEW spoke must exist on the
hub to exercise this capability. ACTIVE if a PENDING_REVIEW spoke exists and ?principal holds networkconnectivity
.spokes.update (effective). CONDITIONAL(iam_permission) if the effective-permission evaluator cannot
confirm the permission.
confidence: '0.90'
derived_from:
- '<effective permission: networkconnectivity.spokes.update on hub project>'
- <presence of at least one Spoke with state=PENDING_REVIEW on the hub>
false_positive_note: (1) This rule only emits when a PENDING_REVIEW spoke exists. If all spokes are
ACTIVE or no spokes exist, downgrade to POTENTIAL. (2) networkconnectivity.spokes.update on the hub
project allows accepting spokes when requireAcceptance=true. On auto-accept hubs (requireAcceptance
=false), this permission is redundant because spokes auto-approve. (3) An IAM Deny policy blocking
networkconnectivity.spokes.update or VPC Service Controls blocking the API should downgrade to BLOCKED.
narrative: "{principal.name} holds networkconnectivity.spokes.update on hub project {hub_project.name}\
\ and can accept PENDING_REVIEW spokes on NCC Hub {hub.name}. An attacker who has created a pending\
\ spoke attaching their VPC to {hub.name} would be immediately approved, placing the attacker's network\
\ on the hub's routing fabric and opening routing to all other spoke-attached VPCs \u2014 a direct\
\ bypass of hub owner approval."