Back to Checks
Firewall does not expose TCP port 22 (SSH) to the Internet
compute_firewall_ssh_access_from_the_internet_allowed
Service: computeSeverity: critical
OfficialBuilt-inVerified
Categories:internet-exposed
Resource Type:compute.googleapis.com/Firewall
VPC firewall rules allowing Internet-sourced ingress (0.0.0.0/0) to TCP port 22 (SSH) are identified, including rules using protocol all or tcp whose ports or ranges include 22.
Risk
Exposed SSH (22) enables Internet-wide scanning, brute force and credential stuffing. Compromise can yield shell access for data exfiltration, command execution, and lateral movement, undermining confidentiality and integrity, and risking availability through abuse or lockouts.
Run this check with Prowler
Run in Prowler CloudRun
prowler gcp --checks compute_firewall_ssh_access_from_the_internet_allowedRecommendation
Restrict SSH to trusted sources; avoid 0.0.0.0/0. Prefer bastion hosts or IAP TCP forwarding, or use VPN/peering. Enforce least privilege and defense in depth: limit to required CIDRs, use key-based auth, disable PasswordAuthentication, and monitor/alert on access attempts.
Remediation
CLI
gcloud compute firewall-rules update <example_resource_name> --source-ranges=<TRUSTED_CIDR>Terraform
resource "google_compute_firewall" "<example_resource_name>" {
name = "<example_resource_name>"
network = "<example_resource_id>"
source_ranges = ["<TRUSTED_CIDR>"] # Critical: removes 0.0.0.0/0 to stop exposing SSH to the Internet
allow {
protocol = "tcp" # Critical: limit to SSH only
ports = ["22"]
}
}Other
1In Google Cloud Console, go to Networking > VPC network > Firewall
2Locate the INGRESS rule that allows tcp:22 with Source IPv4 ranges set to 0.0.0.0/0 and open it
3Click Edit
4Replace Source IPv4 ranges from 0.0.0.0/0 to your trusted CIDR (e.g., <TRUSTED_CIDR>)
5Click Save
Check Code
from prowler.lib.check.models import Check, Check_Report_GCP
from prowler.providers.gcp.services.compute.compute_client import compute_client
class compute_firewall_ssh_access_from_the_internet_allowed(Check):
def execute(self) -> Check_Report_GCP:
findings = []
for firewall in compute_client.firewalls:
report = Check_Report_GCP(
metadata=self.metadata(),
resource=firewall,
location=compute_client.region,
)
report.status = "PASS"
report.status_extended = f"Firewall {firewall.name} does not expose port 22 (SSH) to the internet."
opened_port = False
for rule in firewall.allowed_rules:
if rule["IPProtocol"] == "all":
opened_port = True
break
elif rule["IPProtocol"] == "tcp":
if rule.get("ports") is None:
opened_port = True
break
else:
for port in rule["ports"]:
if port.find("-") != -1:
lower, higher = port.split("-")
if int(lower) <= 22 and int(higher) >= 22:
opened_port = True
break
elif int(port) == 22:
opened_port = True
break
if (
"0.0.0.0/0" in firewall.source_ranges
and firewall.direction == "INGRESS"
and opened_port
):
report.status = "FAIL"
report.status_extended = f"Firewall {firewall.name} does exposes port 22 (SSH) to the internet."
findings.append(report)
return findings