This check flags GCP firewall rules that expose MongoDB (port 27017) to the public internet (0.0.0.0/0). An exposed database invites automated ransomware and data theft, so lock the rule down to internal CIDRs or a bastion and let no untrusted source touch 27017.
Open MongoDB instances are one of the most reliably exploited misconfigurations on the public internet. Bots scan the entire IPv4 space for port 27017 around the clock, and an exposed instance with weak or no authentication can be wiped, ransomed, or quietly siphoned within hours of going live. The Firewall Allows Public MongoDB check looks at your GCP VPC firewall rules and raises a finding when any rule permits inbound traffic to TCP port 27017 from a public source range.
What this check detects
The vpc_openmongodb check inspects ingress firewall rules in your GCP project and flags any rule that meets all of these conditions:
- Direction is INGRESS
- Action is allow
- The rule covers TCP port 27017 (directly, in a port range, or via an all-ports rule)
- The source range includes a public block such as
0.0.0.0/0
MongoDB also commonly listens on 27018 and 27019 for shard and config server roles, and 28017 for the legacy HTTP status interface. This check focuses on the primary database port, but the same exposure logic applies to those neighbors, so treat a finding here as a prompt to audit the whole range.
Note: GCP firewall rules apply at the VPC network level and attach to instances by target tags or service accounts. A single overly broad rule can expose every VM that happens to carry the matching tag, which is why these rules are easy to get wrong at scale.
Why it matters
MongoDB has a long, ugly history of mass compromise. Between 2017 and 2020, waves of ransom attacks hit tens of thousands of internet-facing MongoDB instances. Attackers connected to open databases, exported or deleted the data, and left a ransom note demanding Bitcoin. None of that required a sophisticated exploit. The databases were simply reachable and, in many cases, running without authentication.
Here is what a realistic attack chain looks like when port 27017 is open to the world:
- A scanning service like Shodan or a custom bot finds your IP responding on 27017.
- The bot attempts an unauthenticated connection. Older MongoDB defaults bound to all interfaces with no auth, and plenty of self-managed deployments never turned it on.
- If it connects, the attacker enumerates databases, dumps collections, and either exfiltrates the data or drops it and leaves a ransom note.
- Even with auth enabled, the open port becomes a target for credential stuffing, brute force, and any future CVE in the wire protocol.
Danger: An exposed MongoDB instance holding customer records is a reportable data breach in most jurisdictions. Beyond the technical cleanup, you may be looking at GDPR or CCPA notification obligations, regulatory fines, and contractual penalties. The firewall rule is the cheap thing to fix. The breach is not.
The business impact compounds because databases rarely sit alone. A compromised MongoDB host often hands an attacker a foothold inside your VPC, internal service credentials stored in the database, and a pivot point toward the rest of your environment.
How to fix it
The goal is to remove public access to 27017 and replace it with tightly scoped internal access. Work through the steps below.
1. Find the offending rule
List firewall rules that allow port 27017 and inspect their source ranges:
gcloud compute firewall-rules list \
--filter="allowed.ports=27017 AND direction=INGRESS" \
--format="table(name, network, sourceRanges.list(), targetTags.list(), allowed[].map().firewall_rule().list())"
Look for any rule whose source range is 0.0.0.0/0 or another public block. Note the rule name before making changes.
2. Decide who actually needs access
Application servers should reach MongoDB over the internal VPC network, not the public internet. Identify the legitimate consumers: app subnet CIDRs, a bastion host, or a specific service account.
Warning: Tightening a firewall rule can break production if an application currently depends on the public path. Confirm where your clients connect from before you change the source range, and roll out during a maintenance window if you are unsure.
3. Restrict the source range
Update the rule to allow only your internal CIDR. Replace the placeholder with your real application subnet:
gcloud compute firewall-rules update allow-mongodb \
--source-ranges=10.0.1.0/24
If a temporary admin needs access from a known office IP, scope it to a single address rather than a broad block:
gcloud compute firewall-rules update allow-mongodb \
--source-ranges=10.0.1.0/24,203.0.113.42/32
4. Or delete the rule outright
If nothing legitimately needs the public rule, remove it. Internal traffic within the same VPC is typically covered by a separate, narrower allow rule.
Danger: Deleting a firewall rule is immediate and can sever live connections. Confirm the rule is the public one (not your internal allow rule) and that no production client depends on it before running this command.
gcloud compute firewall-rules delete allow-mongodb-public
5. Harden MongoDB itself
The firewall is one layer. Make sure the database is not relying on network position alone:
- Enable authentication and create least-privilege roles instead of using a single admin user.
- Bind
mongodto the private interface in/etc/mongod.confrather than0.0.0.0. - Enable TLS for client connections so credentials are never sent in the clear.
net:
port: 27017
bindIp: 10.0.1.10
tls:
mode: requireTLS
certificateKeyFile: /etc/ssl/mongodb.pem
security:
authorization: enabled
How to prevent it from happening again
Manual cleanup fixes today's finding. Automation stops the next one from shipping. Define the rule in infrastructure as code, then gate changes in CI.
Codify the rule in Terraform
Here the source range is an internal CIDR, never a public block. Any pull request that widens it becomes visible in review:
resource "google_compute_firewall" "mongodb_internal" {
name = "allow-mongodb-internal"
network = google_compute_network.main.name
allow {
protocol = "tcp"
ports = ["27017"]
}
direction = "INGRESS"
source_ranges = ["10.0.1.0/24"]
target_tags = ["mongodb"]
}
Block public database ports in CI with OPA
A policy-as-code check can fail the pipeline before a bad rule ever reaches GCP. This Rego policy rejects any plan that opens 27017 to the world:
package terraform.firewall
deny[msg] {
rule := input.resource_changes[_]
rule.type == "google_compute_firewall"
allow := rule.change.after.allow[_]
port := allow.ports[_]
port == "27017"
src := rule.change.after.source_ranges[_]
src == "0.0.0.0/0"
msg := sprintf("Firewall '%s' exposes MongoDB (27017) to 0.0.0.0/0", [rule.change.after.name])
}
Tip: Wire this check into a terraform plan -out=tfplan step, convert it with terraform show -json tfplan, and run it through conftest test. You catch the misconfiguration in seconds during review instead of weeks later during an incident.
Enforce org-wide guardrails
For defense beyond the pipeline, use a GCP Organization Policy or Hierarchical Firewall Policy to deny ingress on sensitive ports across every project. That way a single misconfigured project cannot expose a database even if its own rules slip through review. Pair this with continuous scanning in Lensix so any drift from the approved state surfaces immediately rather than waiting for the next audit.
Best practices
- Never put databases on a public source range. Databases belong on private subnets, reachable only from application tiers and a bastion.
- Use target tags or service accounts, not broad networks. Scope each firewall rule to the smallest set of instances that needs it.
- Reach databases through a bastion or IAP. GCP Identity-Aware Proxy lets admins connect to private resources without exposing any port publicly.
- Consider managed alternatives. MongoDB Atlas or a managed deployment handles auth, TLS, and network isolation defaults better than a hand-rolled VM.
- Audit all data-store ports, not just 27017. Apply the same scrutiny to PostgreSQL (5432), MySQL (3306), Redis (6379), and Elasticsearch (9200).
- Monitor continuously. A rule that is correct today can be loosened tomorrow by a rushed change. Ongoing checks catch that drift.
Closing port 27017 to the public internet is a five-minute change that removes one of the most heavily exploited attack surfaces in cloud computing. Make the fix, codify it, gate it in CI, and the same finding will not come back.

