Description
This rule verifies that no DigitalOcean Cloud Firewall permits PostgreSQL (TCP port 5432) from an unrestricted source. Cloud Firewalls are DigitalOcean's equivalent of a security group; an unrestricted source is 0.0.0.0/0 (All IPv4) or ::/0 (All IPv6).
The rule enumerates every firewall's inbound_rules and flags any rule whose protocol is TCP, whose ports include 5432, and whose sources include 0.0.0.0/0 or ::/0. This applies to self-managed PostgreSQL running on Droplets; DigitalOcean Managed Databases are governed by their own trusted-source settings rather than Cloud Firewalls.
Remediation narrows the source of the port-5432 rule to specific application server IPs, a resource tag, or the VPC/private network, and removes the unrestricted rule once connectivity through the scoped path is verified.
Inbound TCP rules on port 5432 with source 0.0.0.0/0
Inbound TCP rules on port 5432 with source ::/0
Port-range or 'all' rules encompassing port 5432 from an unrestricted source
Rationale
A publicly reachable PostgreSQL port exposes the database engine's authentication directly to the internet, bypassing all application-layer safeguards. Automated scanners probe for open port 5432 and attempt weak-credential logins or exploitation of known PostgreSQL vulnerabilities; a successful connection can result in data exfiltration, ransom, or destruction of the dataset.
Databases should be reachable only from the application tier that uses them. Scoping the inbound rule to specific app-server addresses, a tag, or the private VPC network keeps PostgreSQL off the public internet while preserving legitimate access.
Direct database exposure bypasses application-layer protection
Open 5432 is routinely scanned for weak credentials and CVEs
Private-network / tag scoping limits access to the app tier
Impact
Pros:
Removes PostgreSQL from public reachability
Confines database access to the application tier or private network
Reduces exposure to brute-force and PostgreSQL CVE exploitation
Cons:
Requires an accurate inventory of app-server IPs, tags, or VPC range
A missed allowed source can break application connectivity
Direct external database tooling must move behind the allowed path
Default Value
DigitalOcean firewalls suggest only an SSH (port 22) inbound rule on creation and deny all other inbound traffic by default, so any port-5432 exposure was configured deliberately.
Pre-Requisite
Control Panel access with permission to view and edit firewalls
A DigitalOcean API token or doctl authenticated for API/CLI checks
Knowledge of the application server IPs, resource tag, or VPC/private network that must reach PostgreSQL
Remediation
Test Plan
Using the DigitalOcean Control Panel:
Sign in to cloud.digitalocean.com and go to Networking, then Firewalls.
Open each firewall and select the Rules tab.
Under Inbound Rules, look for a PostgreSQL rule or any Custom TCP rule whose Ports include 5432.
Inspect the Sources for that rule and note whether it lists 'All IPv4' and/or 'All IPv6'.
Pass: No inbound rule allowing TCP port 5432 has a source of All IPv4 (0.0.0.0/0) or All IPv6 (::/0).
Fail: At least one inbound rule allows TCP port 5432 from All IPv4 or All IPv6.
Using doctl or the API:
Enumerate firewalls and inspect inbound rules for port 5432 open to an unrestricted source.
doctl compute firewall list --format ID,Name,InboundRules
curl -s -X GET -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" "https://api.digitalocean.com/v2/firewalls" | jq '.firewalls[] | {id, name, offending: [.inbound_rules[] | select(.protocol=="tcp" and (.ports=="5432" or .ports=="0") and (.sources.addresses // [] | any(.=="0.0.0.0/0" or .=="::/0")))]}'
Pass: the offending array is empty for every firewall. Fail: any firewall returns an inbound TCP rule covering port 5432 with a source of 0.0.0.0/0 or ::/0.
Implementation Steps
Using the DigitalOcean Control Panel:
In Networking, then Firewalls, open the firewall and select the Rules tab.
Click Add inbound rule, choose PostgreSQL (or Custom TCP port 5432), and set Sources to the specific app-server IPs, a resource tag, or the VPC/private network range.
Save the rule and confirm the application still reaches the database through the scoped path.
Find the original port-5432 rule whose source is All IPv4 / All IPv6, open its … (More) menu, and choose Delete rule.
Repeat for every firewall exposing PostgreSQL to an unrestricted source.
Using doctl or the API:
Add a scoped port-5432 rule, then remove the unrestricted one.
doctl compute firewall add-rules <firewall-id> --inbound-rules "protocol:tcp,ports:5432,address:10.10.0.0/16"
doctl compute firewall remove-rules <firewall-id> --inbound-rules "protocol:tcp,ports:5432,address:0.0.0.0/0"
curl -s -X POST -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" -H "Content-Type: application/json" -d '{"inbound_rules":[{"protocol":"tcp","ports":"5432","sources":{"addresses":["10.10.0.0/16"]}}]}' "https://api.digitalocean.com/v2/firewalls/<firewall-id>/rules"
curl -s -X DELETE -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" -H "Content-Type: application/json" -d '{"inbound_rules":[{"protocol":"tcp","ports":"5432","sources":{"addresses":["0.0.0.0/0","::/0"]}}]}' "https://api.digitalocean.com/v2/firewalls/<firewall-id>/rules"
Backout Plan:
If application connectivity breaks, temporarily re-add the prior rule with doctl compute firewall add-rules <firewall-id> --inbound-rules "protocol:tcp,ports:5432,address:0.0.0.0/0" (or the equivalent POST /rules) while you correct the allowed sources.
Re-apply the scoped rule and remove the unrestricted rule once the correct app-server sources or VPC range are confirmed.