VPC peering connection route tables do not include 0.0.0.0/0 or entire requester/accepter VPC CIDR routes
AWS VPC peering route tables are assessed for least-privilege routing. Routes that target 0.0.0.0/0 or an entire peer VPC CIDR are considered overly broad; only specific subnets or narrower prefixes should be advertised across the peering link.
Risk
Broad peering routes expand cross-VPC reachability, enabling lateral movement and unauthorized discovery, harming confidentiality and integrity. Using 0.0.0.0/0 or full-CIDR paths also increases misrouting with overlapping ranges, reducing network availability.
Run this check with Prowler
Run in Prowler Cloudprowler aws --checks vpc_peering_routing_tables_with_least_privilegeRecommendation
Enforce least privilege in peering: advertise only required subnets or more specific prefixes; avoid 0.0.0.0/0 and whole VPC ranges. Keep routes symmetric on both sides, and layer defense in depth with security groups and NACLs. If broad connectivity is required, prefer segmented designs or a transit gateway.
Remediation
Terraform
# Restrict VPC peering route to a specific subnet (least privilege)
resource "aws_route" "peering_specific" {
route_table_id = "<example_resource_id>"
destination_cidr_block = "10.0.1.0/24" # CRITICAL: specific subnet, not 0.0.0.0/0 or full VPC CIDR
vpc_peering_connection_id = "<example_resource_id>"
}NativeIaC
# CloudFormation: restrict VPC peering route to a specific subnet (least privilege)
Resources:
PeeringSpecificRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId: <example_resource_id>
DestinationCidrBlock: 10.0.1.0/24 # CRITICAL: use a specific subnet, not 0.0.0.0/0 or full VPC CIDR
VpcPeeringConnectionId: <example_resource_id>Other
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.vpc.vpc_client import vpc_client
class vpc_peering_routing_tables_with_least_privilege(Check):
def execute(self):
findings = []
for peer in vpc_client.vpc_peering_connections:
report = Check_Report_AWS(metadata=self.metadata(), resource=peer)
report.status = "PASS"
report.status_extended = (
f"VPC Peering Connection {peer.id} comply with least privilege access."
)
comply = True
# Check each cidr in the peering route table
for route_table in peer.route_tables:
for cidr in route_table.destination_cidrs:
if (
cidr == "0.0.0.0/0"
or cidr == peer.requester_cidr
or cidr == peer.accepter_cidr
): # Check if cidr does not accept whole requester/accepter VPC CIDR
comply = False
if not comply:
report.status = "FAIL"
report.status_extended = f"VPC Peering Connection {peer.id} does not comply with least privilege access since it accepts whole VPCs CIDR in its route tables."
findings.append(report)
return findings