OPEN_SSH_PORT is a Google Cloud Security Command Center finding that means a VPC firewall rule allows SSH (TCP or SCTP port 22) from any address, usually 0.0.0.0/0. Fix it by deleting the rule or narrowing its source ranges to your admin network, or to the IAP range 35.235.240.0/20, and connecting with gcloud compute ssh –tunnel-through-iap.
What the scanner is actually detecting
This is a configuration finding about a firewall rule, not about the VM or its SSH daemon. Nothing on the guest is scanned. The finding’s resource is the firewall rule itself (asset type compute.googleapis.com/Firewall), so the fix happens in the VPC, not on the host.
| Scanner | Finding title | What it checks |
|---|---|---|
| Security Command Center, Security Health Analytics (FIREWALL_SCANNER) | Open SSH port, category OPEN_SSH_PORT: “A firewall is configured to have an open SSH port that allows generic access.” | Whether a rule that allows generic access has the SSH ports TCP:22 and SCTP:22 in its allowed property. Available in the Standard and Premium tiers, with real-time scans. |
| Microsoft Defender for Cloud (GCP connector) | Firewall should not be configured to have an open SSH port that allows generic access (Low) | The same TCP:22 and SCTP:22 check on the firewall rule metadata. |
| Microsoft Defender for Cloud (GCP connector) | Ensure that SSH access is restricted from the internet (High) | Generic (0.0.0.0/0) ingress to SSH on port 22. |
Google maps OPEN_SSH_PORT to CIS Google Cloud Platform Foundation Benchmark control 3.6 (versions 1.0 through 3.0), NIST 800-53 SC-7 and PCI DSS v4.0 requirements 1.2.1 and 1.4.1. The related OPEN_FIREWALL detector excludes tcp:22 and sctp:22 from its 0.0.0.0/0 check, so a rule that opens only SSH is reported under OPEN_SSH_PORT. One detail catches people out: Google generates this finding even when the rule is disabled, because a disabled rule would expose SSH again as soon as someone re-enables it. If you move these findings into a ticketing or reporting pipeline, our guide to exporting GCP Security Command Center findings covers the export options.
Real-world risk
A rule that allows port 22 from 0.0.0.0/0 exposes every VM it targets that has an external IP address. Internet-wide scanners find open SSH ports quickly, and exposed hosts routinely receive password-guessing traffic. Key-only authentication makes brute force impractical, but the daemon is still reachable if a pre-authentication flaw appears, as happened with OpenSSH CVE-2024-6387 in 2024.
The most common cause is the default network. Every new project gets one unless an organization policy prevents it, and it comes with default-allow-ssh: ingress, priority 65534, source 0.0.0.0/0, tcp:22, with no target tags, so it applies to every instance in that network. A second cause is creating a rule without a source: if you omit –source-ranges and –source-tags, Google Cloud uses 0.0.0.0/0.
VMs with only internal IPs are not reachable from the internet through this rule, so the exposure is smaller. The rule still admits any source that can route into the VPC, such as peered networks or VPN-connected sites.
How to confirm it
List the active findings for a project (you can also pass an organization or folder ID):
gcloud scc findings list projects/PROJECT_ID
--filter='state="ACTIVE" AND category="OPEN_SSH_PORT"'
The resource name in each finding identifies the firewall rule. To review all ingress rules, use this format, adapted from Google’s firewall troubleshooting docs:
gcloud compute firewall-rules list --filter="direction=INGRESS"
--format="table(name, network, disabled, priority,
sourceRanges.list():label=SRC_RANGES,
allowed[].map().firewall_rule().list():label=ALLOW,
targetTags.list():label=TARGET_TAGS)"
Look for 0.0.0.0/0 (or ::/0 on IPv6 rules) in SRC_RANGES together with tcp:22, sctp:22, a port range that includes 22, or all protocols in ALLOW. Save the full rule before you change it, because you will need it for rollback:
gcloud compute firewall-rules describe RULE_NAME --format=json > RULE_NAME-backup.json
Next, find the VMs the rule actually reaches. An empty TARGET_TAGS column means every instance in the network. gcloud compute instances list shows an EXTERNAL_IP column, and –filter=”tags.items=TAG” narrows the list to instances with a given network tag. Then, from a machine outside Google Cloud, test one external address:
nc -vz EXTERNAL_IP 22
How to fix it
Option 1: narrow the rule to a known admin range
If administrators connect from fixed egress addresses (an office, a VPN concentrator, a bastion), replace the source range. The value you pass replaces the existing source ranges rather than adding to them:
gcloud compute firewall-rules update RULE_NAME
--source-ranges=203.0.113.0/24
In the console, go to the Firewall page, click the rule named in the finding, click Edit, delete 0.0.0.0/0 under Source IP ranges, add the specific ranges, then click Save. These are the steps Google gives for this finding.
Option 2: replace public SSH with IAP TCP forwarding
Identity-Aware Proxy (IAP) TCP forwarding lets you drop direct SSH from the internet. The VM does not need an external IP address. Allow port 22 only from the range IAP uses for TCP forwarding:
gcloud compute firewall-rules create allow-ssh-ingress-from-iap
--network=NETWORK
--direction=INGRESS
--action=allow
--rules=tcp:22
--source-ranges=35.235.240.0/20
For IPv6 VMs the IAP range is 2600:2d00:1:7::/64. A single firewall rule can hold IPv4 or IPv6 ranges, not both, so create a second rule for it. Next, grant the IAP-secured Tunnel User role to the admins who need access (Google’s table also lists Compute Instance Admin (v1) for SSH access):
gcloud projects add-iam-policy-binding PROJECT_ID
--member=user:EMAIL
--role=roles/iap.tunnelResourceAccessor
Connect through the tunnel:
gcloud compute ssh VM_NAME --zone=ZONE --tunnel-through-iap
Once the tunnel works, delete the broad rule or narrow it as in Option 1. Google notes that default-allow-ssh admits SSH from all IP addresses, not only from IAP, and suggests disabling or deleting it. Disabling alone does not close OPEN_SSH_PORT, though.
Option 3: remove default-allow-ssh from the default network
gcloud compute firewall-rules delete default-allow-ssh
Longer term, move workloads to a custom VPC network and set the organization policy constraint compute.skipDefaultNetworkCreation, so new projects no longer get a default network with this rule.
How to verify the fix and rescan
- Run gcloud compute firewall-rules describe RULE_NAME and confirm that sourceRanges no longer contains 0.0.0.0/0 (or that the rule is gone).
- Repeat nc -vz EXTERNAL_IP 22 from outside Google Cloud. A new connection should now time out.
- Check the IAP path with gcloud compute ssh VM_NAME –zone=ZONE –troubleshoot –tunnel-through-iap, which tests connectivity, permissions and IAP port forwarding.
- Re-run the gcloud scc findings list command. Security Health Analytics sets a remediated finding to INACTIVE the next time it scans. How long that takes depends on the scan schedule, although this detector supports real-time scans. Defender for Cloud re-evaluates on its own schedule.
- If an external vulnerability scanner also reported port 22 open on the VM’s public IP, rescan that address.
What can break and how to roll back
- The console SSH button. SSH-in-browser reaches a VM through its external IP only if the VPC allows TCP ingress from 0.0.0.0/0. It uses IAP only when the VM has no external IP. With the IAP rule from Option 2 in place, removing the public IP or using gcloud with –tunnel-through-iap restores access.
- Automation. CI/CD deployers, configuration management, backup jobs and vendor support may connect over port 22 from addresses you have not listed. Before tightening, you can run gcloud compute firewall-rules update RULE_NAME –enable-logging for a while to see who connects.
- Corporate proxies. Admins behind a proxy without Cloud VPN need the IAP for TCP domain allowlisted.
- Misleading tests. Cloud NGFW applies rule changes to new connections only. Existing SSH sessions keep working, so an open session proves nothing.
To roll back, recreate the rule with the values from your backup file. For default-allow-ssh it looks like this, with ADMIN_CIDR replaced by the original source range or, better, by your admin network:
gcloud compute firewall-rules create default-allow-ssh
--network=default --direction=INGRESS --action=allow
--rules=tcp:22 --priority=65534 --source-ranges=ADMIN_CIDR
If you must roll back fully, use the original 0.0.0.0/0 only as a temporary measure. Rolling back to a known admin CIDR usually restores access without reopening the finding.
Common false positive reasons
- The rule is disabled. This is by design. Google flags disabled rules because they become exposure again when re-enabled. Delete or narrow the rule.
- Another layer blocks the traffic. A higher-priority deny rule or a firewall policy may drop port 22 before this rule applies. The detector evaluates the rule itself, so it still reports the finding. Tighten the rule anyway, because the other layer can change.
- No exposed VMs. The rule’s target tags match no instances, or the targets have no external IP. Real exposure is low or zero, but the configuration is still wide open for the next VM that matches.
- Intended exposure. A public SFTP endpoint or a hardened bastion host is an accepted risk rather than a false positive. Document it and mute the finding. Google warns against muting remediated findings on existing resources, because a muted finding that becomes active again is easy to miss.
FAQ
Does disabling the firewall rule clear OPEN_SSH_PORT?
No. Google generates the finding for disabled rules too. Delete the rule or remove 0.0.0.0/0 from its source ranges.
Is allowing 35.235.240.0/20 on port 22 safe?
It is far narrower than 0.0.0.0/0. Google documents it as the range containing all IP addresses IAP uses for TCP forwarding, and IAP decides who may open a tunnel through IAM roles such as roles/iap.tunnelResourceAccessor. The SSH daemon still performs its own authentication.
Does the VM need an external IP to use IAP?
No. IAP TCP forwarding works with internal-only VMs, and removing external IPs is a good follow-up step.
My SSH only accepts keys. Is this still a finding?
Yes. The detector evaluates the firewall rule, not how sshd authenticates. Key-only authentication lowers the risk, but the port is still reachable from the whole internet. For how this kind of check fits into cloud posture tooling, see what CSPM is and what it cannot detect.
Tracking this finding across many hosts
OPEN_SSH_PORT is closed in the VPC, but the VMs behind the rule often carry host-level SSH findings as well. SITEY, a self-hosted vulnerability management platform, imports findings from 16 scanners into one queue and merges duplicates within each scanner (not across scanners). Its AI triage suggests false positives with supporting evidence, and a person makes the final call.