AWS VPC Default Configuration Security Risks: 5 Critical Vulnerabilities and Mitigation Strategies

The default AWS VPC automatically attaches an Internet Gateway and assigns public IP addresses to new instances, creating immediate internet exposure risks that require custom VPC architecture, hardened security groups, and explicit subnet policies to mitigate.

When you create a new AWS account, AWS provisions a default VPC in every Region to help users launch resources quickly. According to the bregman-arie/devops-exercises repository, this convenience-first configuration includes an Internet Gateway (IGW), a main route table with a 0.0.0.0/0 → IGW route, and subnets that automatically assign public IPv4 addresses. While this enables instant connectivity, it introduces significant AWS VPC default configuration security risks that can expose internal services to brute-force attacks, data exfiltration, and lateral movement.

Understanding the Default AWS VPC Layout

The default VPC composition is documented in topics/aws/README.md at lines 1187-1203 of the devops-exercises repository. Every new account receives exactly one default VPC per Region containing:

  • An Internet Gateway attached to the main route table
  • A default route sending all traffic (0.0.0.0/0) to the IGW
  • Public subnets that map public IP addresses on launch
  • A default security group allowing all traffic from itself (intra-VPC)
  • A default network ACL allowing all inbound and outbound traffic

This architecture prioritizes accessibility over security, making it unsuitable for production workloads without significant hardening.

Principal Security Risks in Default AWS VPC Configurations

Internet-Exposed Instances

The most severe risk is automatic internet exposure. Because the default route table sends all traffic to the IGW and subnets assign public IPs by default, any EC2 instance launched without explicit configuration receives a public IPv4 address and is reachable from the internet. This creates accidental exposure of databases, management interfaces, and internal services to global scanning and brute-force attacks.

Permissive Default Security Groups

The default security group implements a self-referencing allow-all rule that permits unrestricted traffic between any instances attached to the same group. While it blocks inbound internet traffic by default, if an instance is accidentally associated with an internet-facing security group or IGW, the self-referencing rule enables lateral movement between compromised instances within the VPC.

Overly Permissive Network ACLs

The default network ACL allows all inbound and outbound traffic with a "allow all" policy. When teams add custom NACLs to specific subnets, they often forget that the default NACL still permits everything on unassociated subnets. This creates bypass opportunities where unintended traffic can reach management ports or sensitive services despite restrictive subnet-level policies.

Automatic Public DNS and IP Allocation

Every instance launched in the default VPC automatically receives a public DNS hostname and public IPv4 address unless explicitly disabled. This makes internal services trivially discoverable through automated scanning and DNS enumeration, increasing the attack surface for credential-stuffing and reconnaissance activities.

Shared Resource Contamination

Because AWS limits each Region to one default VPC, multiple teams or environments often share the same network boundary. This breaks data isolation assumptions and creates "trust-but-verify" failures where development resources can accidentally communicate with production workloads through the shared default security group or route table.

Mitigation Strategies for Default AWS VPC Risks

Delete or Isolate the Default VPC

The safest approach is to delete the default VPC entirely or at minimum detach its Internet Gateway. This forces all resource launches to use intentionally designed VPCs where networking is explicitly configured rather than inherited from insecure defaults.

Build Custom Locked-Down VPCs with Terraform

Replace the default VPC with infrastructure-as-code definitions that implement security by design. The devops-exercises repository provides a minimal VPC definition in topics/aws/exercises/new_vpc/terraform/main.tf that you can extend to create private-only networks without IGW attachments.

Implement Deny-All Security Group Baselines

Create custom security groups that start with zero inbound rules (implicit deny-all) and explicitly add only required ports and sources. Disable the default security group by revoking all its ingress rules using the AWS CLI:

aws ec2 revoke-security-group-ingress \
  --group-id sg-xxxxxxxx \
  --protocol all \
  --source-group sg-xxxxxxxx

Deploy Custom Network ACLs

Replace the default "allow all" NACL with custom network ACLs that explicitly deny traffic by default. Associate these with every subnet to ensure that only approved protocols and ports can traverse subnet boundaries, preventing exposure of management interfaces like SSH or RDP.

Disable Automatic Public IP Assignment

In your subnet configurations, explicitly set map_public_ip_on_launch = false to prevent automatic public IP assignment. This is demonstrated in topics/aws/exercises/subnets/terraform/main.tf and ensures instances remain private unless you explicitly allocate Elastic IPs for specific use cases.

Enable Continuous Monitoring

Deploy AWS Config rules to flag any resources attached to the default VPC or security groups allowing 0.0.0.0/0 ingress. Enable GuardDuty to detect publicly exposed services and anomalous connection patterns that indicate misconfigured network boundaries.

Terraform Implementation: Secure VPC Architecture

The following Terraform configuration implements a hardened VPC design based on the devops-exercises repository examples. This creates a private-only VPC without internet exposure, using explicit NACL rules and deny-all security groups:


# Custom VPC without Internet Gateway attachment

# Based on topics/aws/exercises/new_vpc/terraform/main.tf

resource "aws_vpc" "secure_vpc" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name  = "secure-vpc"
    Owner = "team-security"
  }
}

# Private subnet with disabled public IP mapping

# Extends topics/aws/exercises/subnets/terraform/main.tf

resource "aws_subnet" "private_a" {
  vpc_id                  = aws_vpc.secure_vpc.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = data.aws_availability_zones.available.names[0]
  map_public_ip_on_launch = false

  tags = {
    Name = "private-subnet-a"
  }
}

# Custom Network ACL with explicit deny-by-default posture

resource "aws_network_acl" "private_acl" {
  vpc_id = aws_vpc.secure_vpc.id

  # Allow SSH only from bastion subnet (example: 10.0.0.0/24)

  ingress {
    protocol   = "tcp"
    rule_no    = 100
    action     = "allow"
    cidr_block = "10.0.0.0/24"
    from_port  = 22
    to_port    = 22
  }

  # Explicit deny all other inbound traffic

  ingress {
    protocol   = "-1"
    rule_no    = 200
    action     = "deny"
    cidr_block = "0.0.0.0/0"
  }

  # Allow all outbound (adjust as needed for your use case)

  egress {
    protocol   = "-1"
    rule_no    = 100
    action     = "allow"
    cidr_block = "0.0.0.0/0"
  }

  tags = {
    Name = "private-acl"
  }
}

# Associate NACL with private subnet

resource "aws_network_acl_association" "private_a_assoc" {
  subnet_id      = aws_subnet.private_a.id
  network_acl_id = aws_network_acl.private_acl.id
}

# Hardened Security Group: deny-all inbound by default

resource "aws_security_group" "private_sg" {
  name        = "private-deny-all"
  description = "Deny all inbound, allow outbound"
  vpc_id      = aws_vpc.secure_vpc.id

  # No ingress rules = implicit deny all inbound

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "private-sg"
  }
}

This configuration demonstrates the security principles documented in the devops-exercises repository, transforming the minimal VPC example into a production-grade network architecture.

Summary

  • Default VPCs include Internet Gateways and public IP assignment by default, creating immediate internet exposure risks for new instances.
  • Default security groups allow lateral movement through self-referencing rules that permit unrestricted traffic between attached instances.
  • Default network ACLs allow all traffic, providing no subnet-level protection if custom NACLs are misconfigured or forgotten.
  • Mitigation requires deleting or isolating the default VPC and replacing it with custom Terraform-defined VPCs that disable public IP mapping and implement deny-all security baselines.
  • Continuous monitoring via AWS Config and GuardDuty ensures that deviations from secure configurations are detected immediately.

Frequently Asked Questions

Should I delete the default VPC in AWS?

Yes, deleting the default VPC is recommended for production accounts to prevent accidental launches into insecure network configurations. If deletion is not feasible, detach the Internet Gateway and revoke all security group ingress rules to neutralize the automatic internet exposure risks.

What makes the default security group risky?

The default security group contains a self-referencing rule that allows all traffic from other instances using the same security group. While this does not permit direct internet inbound access, it enables lateral movement between compromised instances and can combine with other misconfigurations to expose internal services.

How do I prevent automatic public IP assignment in AWS?

Set map_public_ip_on_launch = false in your subnet configuration using Terraform or the AWS Console. In the devops-exercises repository, the subnet definition in topics/aws/exercises/subnets/terraform/main.tf demonstrates this parameter, ensuring instances launch with private IPs only unless you explicitly attach an Elastic IP.

Can I use the default VPC securely for production workloads?

Only with significant hardening. You must detach the Internet Gateway, disable automatic public IP assignment on all subnets, replace the default security group with explicit deny-all rules, and implement custom network ACLs. However, creating a dedicated custom VPC as shown in topics/aws/exercises/new_vpc/terraform/main.tf provides a cleaner security boundary and avoids the risks of shared default resources.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →