Skip to main content
cd ../config-traps
risk/register/rds-publiclyaccessible-the-flag-that-bypasses-your-vpc.html
AWS RDS Networkingcritical severityAWS RDS

RDS PubliclyAccessible: The Flag That Bypasses Your VPC

Severity
critical
Reviewed
12 Jul 2026
Remediation
~20 minutes
Overview

An RDS instance stays reachable from the internet the moment PubliclyAccessible is true, even while no security group rule permits it. The exposure lies dormant until an unrelated security group change opens the database port to 0.0.0.0/0, instantly exposing production data to internet scanners.

Operational summary

At a glance

Symptom
An unrelated security group edit adds an internet-wide ingress rule while the public endpoint already exists
Likely cause
PubliclyAccessible=true combined with a security group later allowing 0.0.0.0/0 on the database port
Impact
Internet-wide scanners find the open port within hours, enabling brute force, RCE exploitation, and credential reuse across environments.
Verification signal
Re-run the detection test and a controlled negative-path test.
Safe correction
Disable PubliclyAccessible, enforce via AWS Config rds-instance-public-access-check with automated remediation, and block via SCP.
Rollback or recovery
Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

The Trap

The PubliclyAccessible attribute on an Amazon RDS instance, left set to true and paired with a security group that later gains an inbound rule for 0.0.0.0/0 on the database port.

The Default State

The RDS console quick-create wizard defaults “Public access” to No, but this is routinely overridden. Terraform modules copied from public examples ship with publicly_accessible = true as the sample value, and CloudFormation stacks generated by migration tooling frequently set it explicitly for “testing convenience” during a cutover, then never revert it. Separately, engineers create a dedicated security group during a migration and add an ingress rule for 0.0.0.0/0 on port 5432 or 3306 so an external ETL box or a Lambda outside the VPC can reach the instance during the initial load. Neither setting alone is fatal. Together, they are lethal, because AWS provisions a second, internet-routable DNS endpoint the moment PubliclyAccessible is true, regardless of whether any rule currently permits reaching it.

The Blast Radius

The public endpoint exists and resolves from day one, sitting inert until someone modifies the security group for an unrelated reason: a new integration, a firewall exception ticket, a copy-pasted Terraform block. The instant a 0.0.0.0/0 rule lands on the database port, the previously dormant public endpoint becomes reachable from the entire internet, not just the intended new client. Mass scanners on Shodan and masscan detect the open port within hours. Brute-force attempts against the master username, exploitation of unpatched engine CVEs (MySQL/PostgreSQL RCE chains), and credential stuffing against IAM database authentication follow immediately. Because RDS snapshots inherit the same exposure posture and credentials are frequently reused in Parameter Store or Secrets Manager across environments, one exposed instance often yields lateral access into staging and production simultaneously.

The Lead Mechanic Fix

Disable the flag directly: aws rds modify-db-instance --db-instance-identifier <id> --no-publicly-accessible --apply-immediately. Enforce this at the control-plane level with an AWS Config managed rule, rds-instance-public-access-check, wired to an SSM Automation remediation that runs the same modify command on drift. Block the condition entirely with an SCP denying rds:CreateDBInstance and rds:ModifyDBInstance when the request context includes rds:PubliclyAccessible: true, excepting a tagged sandbox OU. Security groups must reference source security group IDs for application tiers, never CIDR blocks, and any external-integration requirement should route through a VPC endpoint or a bastion with Session Manager port forwarding instead of a public listener.

03

Apply the safer control

Before you change production

Confirm the affected scope, export the current configuration, and test the replacement control in a non-production environment first.

Fix commands and configuration

aws rds modify-db-instance --db-instance-identifier <id> --no-publicly-accessible --apply-immediately
rds-instance-public-access-check
rds:CreateDBInstance
04

Verify, roll back or escalate

Verify

Re-run the detection test and a controlled negative-path test. Confirm the unsafe behaviour is blocked while approved traffic still succeeds.

Rollback

Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

Escalate

Escalate when the blast radius is uncertain, the control cannot be tested safely, or remediation requires an outage or security exception.

After remediation

Further reading stays below the corrective workflow and is selected by platform, category and shared technical keywords.

Discover more

Connected KBY resources