Back to Checks
gcp

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 Cloud
Run
prowler gcp --checks compute_firewall_ssh_access_from_the_internet_allowed

Recommendation

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