This check flags GCP firewall rules that expose RPC (TCP/UDP port 135) to 0.0.0.0/0. Port 135 is the Windows RPC endpoint mapper, a classic lateral-movement and remote-exploit target that should never face the internet. Restrict the rule to a known internal CIDR or delete it.
Port 135 is one of those ports that has no business being reachable from the public internet, yet it shows up exposed more often than you would expect. The Firewall Allows Public RPC check looks at your GCP VPC firewall rules and raises a finding when one of them permits inbound traffic to port 135 from any source. If you are running Windows workloads in Compute Engine, this is almost always a misconfiguration waiting to be abused.
What this check detects
Lensix inspects each ingress firewall rule in your VPC networks and flags any rule that matches all of the following:
- Direction is INGRESS
- Action is allow
- The source range includes
0.0.0.0/0(the entire IPv4 internet) - The allowed ports include 135 over TCP or UDP
Port 135 is the Microsoft RPC Endpoint Mapper (also called the DCE endpoint resolution service). It is the front door that Windows clients use to locate dynamic RPC services such as DCOM, WMI, the Task Scheduler, and a long list of other system components. When a rule opens this port to the world, anyone on the internet can start probing those services.
Note: The endpoint mapper on 135 hands out the higher dynamic ports (typically 49152 to 65535) that individual RPC services actually listen on. Exposing 135 is often the first step that lets an attacker enumerate and reach those downstream services.
Why it matters
RPC has a long, well-documented history of remote code execution vulnerabilities. A few that network defenders still remember vividly:
- MS03-026, the DCOM RPC flaw exploited by the Blaster worm in 2003, which spread to hundreds of thousands of machines through port 135.
- CVE-2022-26809, a critical wormable RPC runtime vulnerability that Microsoft rated as likely to be exploited, reachable through 135.
- Numerous WMI and DCOM-based lateral movement techniques used by ransomware operators once they gain a foothold.
The risk is not just a single CVE. Port 135 gives an attacker a discovery and execution surface. Even when the host is patched, exposing the endpoint mapper lets attackers enumerate services, fingerprint the operating system, and attempt credential relay or null-session attacks. Once one instance is compromised, RPC is also a favored channel for moving laterally to other Windows hosts inside the VPC.
Danger: A public RPC port on a domain-joined Windows instance can expose your entire Active Directory environment. RPC is heavily used for replication, authentication, and remote management, so a single exposed host can become the pivot point for a full domain compromise.
From a compliance standpoint, an open RPC port to 0.0.0.0/0 will fail CIS GCP benchmark controls around restricting ingress, and it will trip up PCI DSS, HIPAA, and SOC 2 network segmentation requirements.
How to fix it
The fix is to stop port 135 from being reachable from the public internet. You have three practical options depending on whether the rule is needed at all.
Step 1: Find the offending rule
List ingress rules and filter for ones that allow 135 from anywhere:
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())"
Inspect any rule that mentions tcp:135 or udp:135 in detail:
gcloud compute firewall-rules describe RULE_NAME --format=json
Step 2a: Restrict the source range
If RPC genuinely needs to be reachable, scope it to the specific internal ranges or bastion addresses that need it. Replace the broad source with your real CIDR blocks:
Warning: Updating --source-ranges replaces the entire list, it does not append. Include every range you intend to keep, or you will accidentally cut off legitimate access.
gcloud compute firewall-rules update RULE_NAME \
--source-ranges=10.0.0.0/8,172.16.0.0/12
Step 2b: Delete the rule entirely
If nothing legitimately needs inbound RPC over the public internet, and it almost never does, remove the rule.
Danger: Deleting a firewall rule takes effect immediately and can break active connections. Confirm that no internal service depends on this rule before running the command.
gcloud compute firewall-rules delete RULE_NAME
Step 2c: Use IAP for Windows management instead
If the real goal was remote administration, use Identity-Aware Proxy TCP forwarding rather than opening ports to the internet. Allow only the IAP range and let Google's proxy handle authentication:
gcloud compute firewall-rules create allow-iap-rdp \
--direction=INGRESS \
--action=allow \
--rules=tcp:3389 \
--source-ranges=35.235.240.0/20 \
--network=default
Tip: The range 35.235.240.0/20 is Google's dedicated IAP forwarding range. Pairing IAP with IAM conditions gives you authenticated, audited access to Windows hosts without ever exposing RPC, RDP, or WinRM to the public internet.
Fixing it in Terraform
If your firewall rules live in Terraform, change the source ranges in code so the fix sticks. A scoped rule looks like this:
resource "google_compute_firewall" "rpc_internal" {
name = "allow-rpc-internal"
network = google_compute_network.vpc.name
direction = "INGRESS"
allow {
protocol = "tcp"
ports = ["135"]
}
# Internal management subnet only, never 0.0.0.0/0
source_ranges = ["10.0.0.0/8"]
target_tags = ["windows-rpc"]
}
How to prevent it from happening again
Manual cleanup does not stop the next engineer from pasting 0.0.0.0/0 into a rule. Push the guardrails left into your pipeline and your org policy.
Block it in CI with policy-as-code
Add a Conftest or OPA policy that fails any plan exposing 135 to the world. A Rego rule for Terraform plans:
package firewall
deny[msg] {
rule := input.resource_changes[_]
rule.type == "google_compute_firewall"
rule.change.after.direction == "INGRESS"
rule.change.after.source_ranges[_] == "0.0.0.0/0"
allow := rule.change.after.allow[_]
allow.ports[_] == "135"
msg := sprintf("Firewall %v exposes RPC port 135 to the public internet", [rule.change.after.name])
}
Wire this into the pipeline so the build breaks before the rule ever reaches GCP:
conftest test plan.json --policy policies/
Enforce it at the org level
GCP Organization Policy does not natively filter ports, but you can combine hierarchical firewall policies with a deny rule that blocks 135 from the internet across every project. Define it once at the org or folder level so individual teams cannot override it.
Tip: Connect Lensix to your GCP organization so this check runs continuously across all projects. Catching a public RPC rule minutes after it is created is far cheaper than discovering it in an incident response timeline.
Best practices
- Default deny, then allow narrowly. Start every VPC with no public ingress and open only the specific ports and ranges you can justify.
- Keep management ports off the internet. RPC (135), RDP (3389), WinRM (5985/5986), SMB (445), and SSH (22) should all be reached through IAP, a VPN, or a bastion, never
0.0.0.0/0. - Use network tags and service accounts as targets. Scope rules to the specific instances that need them rather than applying them network-wide.
- Audit firewall changes. Stream Compute Engine admin activity logs to your SIEM and alert on any new rule containing
0.0.0.0/0. - Review the dynamic port range too. RPC services answer on high dynamic ports after the mapper redirects them. If 135 was open, check whether 49152 to 65535 was also exposed.
- Document exceptions. If a rule must stay broad for a real reason, record the owner and review date so it does not become permanent by accident.
Treat any public RPC exposure as a finding to remediate the same day. The port has been a worm and ransomware highway for two decades, and there is almost no legitimate reason to leave it open to the internet. Lock it down to internal ranges or move administration behind IAP, and add a policy gate so the next pull request cannot reintroduce it.

