This check flags GCP VPC firewall rules that allow inbound traffic on every port from 0.0.0.0/0. That exposes SSH, RDP, databases, and admin panels to the entire internet. Scope the rule to specific ports and trusted source ranges, or delete it.
An open firewall rule is one of the fastest ways to turn a healthy cloud project into an incident. When a GCP firewall rule says "allow all ports from anywhere," every service running on those VMs is reachable by anyone with a scanner and some free time. This check, vpc_openallports in the Lensix vpc_checks module, catches exactly that pattern before an attacker does.
Below we break down what the check looks for, why a wide-open rule is dangerous, and how to fix and prevent it.
What this check detects
Lensix scans your VPC firewall rules and flags any ingress allow rule that combines two risky properties:
- A source range of
0.0.0.0/0(or::/0for IPv6), meaning any public IP address. - A port specification that covers all ports, either
tcp/udpwith no port restriction, or the protocol set toall.
In GCP a firewall rule with allowed set to all protocols and a source of 0.0.0.0/0 effectively opens every TCP and UDP port on every instance the rule targets. If the rule has no target tags or service account filter, it applies to all instances in the VPC network.
Note: GCP firewall rules are stateful and apply at the VPC network level, not per-instance. A single permissive rule can expose hundreds of VMs at once, even ones spun up after the rule was created.
Here is what a flagged rule looks like in gcloud output:
{
"name": "default-allow-all",
"network": "default",
"direction": "INGRESS",
"priority": 1000,
"sourceRanges": ["0.0.0.0/0"],
"allowed": [
{ "IPProtocol": "all" }
]
}
Why it matters
Opening all ports to the internet removes the network layer of defense entirely. Every other control, patching, authentication, intrusion detection, now has to be perfect, because the firewall is doing nothing to help.
Real attack scenarios
- SSH and RDP brute forcing. Ports 22 and 3389 are scanned continuously by botnets. An exposed VM with password auth or a weak key gets hammered within minutes of going live.
- Unauthenticated databases. A MongoDB, Redis, Elasticsearch, or PostgreSQL instance that binds to
0.0.0.0and trusts the network is now reachable. Many of the largest data leaks in the last decade traced back to an exposed database with no auth. - Internal admin panels. Kubernetes dashboards, Jenkins, Prometheus, and similar tools often assume they sit behind a firewall. Exposed, they become a direct path to remote code execution.
- Crypto mining and pivoting. Once one box is compromised, an attacker uses it to scan and move laterally across the VPC, which the wide-open rule makes trivial.
Danger: The default VPC network in GCP historically shipped with permissive rules. If you never reviewed the default network, you may already have default-allow-ssh and similar rules open to 0.0.0.0/0. Audit them today.
Business impact
Beyond the technical risk, an all-ports rule will fail most compliance audits. PCI DSS, SOC 2, HIPAA, and CIS Benchmarks all expect ingress to be restricted to known sources and ports. A single finding like this can hold up a certification or trigger a remediation deadline.
How to fix it
The goal is simple: replace "all ports from anywhere" with "specific ports from trusted sources." Start by finding the offending rules.
1. Identify the rules
gcloud compute firewall-rules list \
--filter="direction=INGRESS AND sourceRanges:0.0.0.0/0" \
--format="table(name, network, sourceRanges.list(), allowed[].map().firewall_rule().list())"
Look for any rule where the allowed protocol is all, or where tcp/udp appear with no port restriction.
2. Decide what actually needs to be open
Most workloads need only a handful of ports exposed, and usually not to the whole internet. Common patterns:
- Public web traffic: ports 80 and 443, open to
0.0.0.0/0but ideally fronted by a load balancer or Cloud Armor. - Admin access (SSH/RDP): restricted to your corporate IP ranges or, better, routed through Identity-Aware Proxy.
- Databases and internal services: restricted to internal VPC ranges only.
3. Tighten or replace the rule
Warning: Narrowing a firewall rule can drop active connections to services that were relying on it. Confirm which ports your instances actually serve before you change anything, and roll out during a maintenance window if production traffic is involved.
Create a tightly scoped replacement rule first, so there is no window where legitimate traffic is blocked:
# Allow only HTTPS from anywhere, targeting tagged web servers
gcloud compute firewall-rules create allow-https-web \
--network=default \
--direction=INGRESS \
--action=ALLOW \
--rules=tcp:443 \
--source-ranges=0.0.0.0/0 \
--target-tags=web-server
# Allow SSH only from your corporate range
gcloud compute firewall-rules create allow-ssh-corp \
--network=default \
--direction=INGRESS \
--action=ALLOW \
--rules=tcp:22 \
--source-ranges=203.0.113.0/24 \
--target-tags=ssh-access
Then remove the permissive rule.
Danger: Deleting a firewall rule is immediate and affects every instance in the network. Double check that nothing depends on the open ports, and that your replacement rules are already in place, before running the command below.
gcloud compute firewall-rules delete default-allow-all
If you cannot delete it yet, you can at least narrow the protocol and ports in place:
gcloud compute firewall-rules update default-allow-all \
--rules=tcp:443 \
--source-ranges=0.0.0.0/0
Tip: For SSH and RDP, skip public exposure entirely and use Identity-Aware Proxy. You then allow only the IAP range 35.235.240.0/20 on port 22 and authenticate through IAM, so no admin port ever touches the open internet.
4. Express it as code
If you manage infrastructure with Terraform, define the scoped rules in version control so the fix sticks:
resource "google_compute_firewall" "allow_https" {
name = "allow-https-web"
network = "default"
direction = "INGRESS"
allow {
protocol = "tcp"
ports = ["443"]
}
source_ranges = ["0.0.0.0/0"]
target_tags = ["web-server"]
}
resource "google_compute_firewall" "allow_ssh_iap" {
name = "allow-ssh-iap"
network = "default"
direction = "INGRESS"
allow {
protocol = "tcp"
ports = ["22"]
}
# IAP TCP forwarding range only
source_ranges = ["35.235.240.0/20"]
target_tags = ["ssh-access"]
}
How to prevent it from happening again
Fixing one rule is easy. Stopping the next one from appearing is where the real value is. Build guardrails at three layers.
Policy as code in CI/CD
Catch permissive rules in pull requests before they reach GCP. With Terraform, a tool like Checkov or tfsec flags an open firewall in seconds:
checkov -d . --check CKV_GCP_2,CKV_GCP_106
Or write an Open Policy Agent rule that fails the plan when a rule combines all ports with a public source:
package firewall
deny[msg] {
rule := input.resource.google_compute_firewall[name]
rule.source_ranges[_] == "0.0.0.0/0"
rule.allow[_].protocol == "all"
msg := sprintf("Firewall '%s' allows all ports from the internet", [name])
}
Organization policy constraints
GCP lets you enforce guardrails at the org level. The constraints/compute.vmExternalIpAccess and custom org policies can block the creation of overly permissive resources centrally, so even a manual change in the console is rejected.
Continuous monitoring
IaC scanning only covers resources created through IaC. Someone with console access can still click their way to an open rule. Continuous scanning with Lensix catches drift no matter how the rule was created, and surfaces the vpc_openallports finding the moment it appears.
Tip: Pair Lensix alerts with a notification channel so an open-all-ports rule pages the on-call engineer rather than sitting unnoticed until the next audit.
Best practices
- Default deny. GCP already denies ingress by default. Keep it that way and add narrow allow rules only as needed, rather than broad rules you plan to tighten later.
- One rule, one purpose. Avoid catch-all rules. A rule per service with explicit ports and target tags is far easier to audit and reason about.
- Use target tags or service accounts. Never let a rule apply to every instance in the network. Scope it to the workloads that genuinely need it.
- Restrict admin ports to private paths. SSH, RDP, and management interfaces belong behind IAP, a bastion, or a VPN, never open to
0.0.0.0/0. - Review the default network. If you are not using the auto-created default VPC, delete it. Its starter rules are more permissive than most teams want.
- Log and review. Enable firewall rules logging on sensitive rules so you have an audit trail of what connected and when.
An open firewall rule is rarely created on purpose. It usually starts as a quick "just make it work" change during a deployment and never gets cleaned up. The fix is cheap, the exposure is expensive, and a single scan plus a CI gate is enough to keep it from coming back.

