Skip to main content
cd ../config-traps
risk/register/rds-publiclyaccessible-fixes-wait-for-maintenance-window.html
AWS RDS Network Exposurecritical severityAWS RDS

RDS PubliclyAccessible Fixes Wait for Maintenance Window

Severity
critical
Reviewed
22 Jul 2026
Remediation
~20 minutes
Overview

An engineer runs modify-db-instance with -no-publicly-accessible but omits -apply-immediately, so AWS defers the change to the next maintenance window while the instance keeps answering on 3306 or 5432 across 0.0.0.0/0. Security Hub, ticketing systems and the engineer all treat the exposure as closed while it remains live for days.

Operational summary

At a glance

Symptom
An audit remediation ticket is closed based on a successful API call while the instance remains publicly reachable until the next maintenance window.
Likely cause
modify-db-instance --no-publicly-accessible is run without --apply-immediately, so the change sits in PendingModifiedValues instead of taking effect.
Impact
The database stays reachable on 0.0.0.0/0 over 3306/5432 for days while dashboards and tickets report the exposure as resolved.
Verification signal
Re-run the detection test and a controlled negative-path test.
Safe correction
Pair PubliclyAccessible changes with --apply-immediately, verify PendingModifiedValues is empty, and enforce closure via AWS Config auto-remediation.
Rollback or recovery
Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

The Trap

Deferred PubliclyAccessible remediation. A database is exposed with PubliclyAccessible: true and a security group ingress rule of 0.0.0.0/0 on port 3306 (MySQL/Aurora) or 5432 (PostgreSQL). An engineer spots this in an audit and runs aws rds modify-db-instance --no-publicly-accessible, closes the ticket, and moves on. The change never actually applies.

The Default State

The AWS CLI’s modify-db-instance command defaults --apply-immediately to false unless explicitly overridden. The Management Console mirrors this: the “Scheduling of modifications” section on the Modify page pre-selects “Apply during the next scheduled maintenance window” rather than “Apply immediately”. Any change to PubliclyAccessible submitted without the immediate flag is written into PendingModifiedValues, not into the live instance state.

The Blast Radius

describe-db-instances continues to return PubliclyAccessible: true until the preferred maintenance window arrives, which can be seven days out, or indefinitely if the window keeps getting skipped because AutoMinorVersionUpgrade is disabled and no other pending change forces a window event. The security group’s 0.0.0.0/0 rule on 3306/5432 is untouched by this modify call entirely, since it’s a separate EC2 resource, so the endpoint remains internet-reachable throughout. Meanwhile the ticket is closed, the change history shows a successful API call, and cached AWS Security Hub findings for control RDS.2 may briefly show resolved. Mass scanners on Shodan and routine masscan sweeps continue to enumerate the open port and attempt master-user credential brute force during the entire gap, with no alerting difference between “fix pending” and “fix applied”.

The Lead Mechanic Fix

Always pair the flag with immediate application and verify state explicitly: aws rds modify-db-instance --db-instance-identifier prod-db --no-publicly-accessible --apply-immediately, then confirm with aws rds describe-db-instances --db-instance-identifier prod-db --query 'DBInstances[0].[PubliclyAccessible,PendingModifiedValues]' until PendingModifiedValues returns empty. Separately revoke the security group rule: aws ec2 revoke-security-group-ingress --group-id sg-xxxxxxxx --protocol tcp --port 3306 --cidr 0.0.0.0/0. For standing enforcement, deploy the AWS Config managed rule rds-instance-public-access-check with automatic remediation via the SSM document AWSConfigRemediation-DisablePublicAccessForRDSInstance, which sets ApplyImmediately=true internally and closes the pending-state gap that manual CLI runs leave open.

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 prod-db --no-publicly-accessible --apply-immediately
aws rds describe-db-instances --db-instance-identifier prod-db --query 'DBInstances[0].[PubliclyAccessible,PendingModifiedValues]'
PendingModifiedValues
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