gcp-firewall-internet-exposed

VM with an ingress ALLOW from 0.0.0.0/0 AND an external IP is internet-exposed on that port - any unauthenticated actor can attempt to connect.

derived gcp emits ExposedToInternet

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'internet': None} CanReachPort {'vm': None}

where

?vm is a VirtualMachine with networkInterfaces[*].accessConfigs[*].natIP non-empty (external IP present) the CanReachPort edge was derived by gcp-firewall-inbound-open (source is 0.0.0.0/0)

emit

source typeCompute
target typeAnonymousIdentity
source<VirtualMachine node (?vm)>
target<AnonymousIdentity>
state logicACTIVE when the VM has a confirmed external IP and no higher-priority DENY shadows the ingress ALLOW rule; CONDITIONAL(network_reachability) if the external IP presence cannot be confirmed at collection time.

Narrative

{vm.name} is directly internet-exposed: firewall rule {firewall_rule.name} allows ingress from 0.0.0.0/0 on {protocol}/{port} and the VM has external IP {external_ip}. Any unauthenticated internet actor can attempt to reach the service on that port.

Raw rule rules/derived/gcp/firewall.yaml

id: gcp-firewall-internet-exposed
emits: ExposedToInternet
description: "VM with an ingress ALLOW from 0.0.0.0/0 AND an external IP is internet-exposed on that port\
  \ \u2014 any unauthenticated actor can attempt to connect."
applies_to:
- gcp
match:
- - internet: null
  - CanReachPort
  - vm: null
where:
- ?vm is a VirtualMachine with networkInterfaces[*].accessConfigs[*].natIP non-empty (external IP present)
- the CanReachPort edge was derived by gcp-firewall-inbound-open (source is 0.0.0.0/0)
emit:
  source_type: Compute
  target_type: AnonymousIdentity
  source: <VirtualMachine node (?vm)>
  target: <AnonymousIdentity>
  permissions: []
  conditions: []
  state_logic: ACTIVE when the VM has a confirmed external IP and no higher-priority DENY shadows the
    ingress ALLOW rule; CONDITIONAL(network_reachability) if the external IP presence cannot be confirmed
    at collection time.
  false_positive_note: "A VM behind a NAT gateway that does not have its own external IP is NOT directly\
    \ internet-exposed even if the firewall allows inbound from 0.0.0.0/0; omit ExposedToInternet for\
    \ NAT-only egress VMs. Cloud Load Balancers present a separate public IP \u2014 the LB exposure is\
    \ captured by the load balancer service rules, not here. Only emit when natIP (external IP on the\
    \ NIC itself) is confirmed present."
  narrative: '{vm.name} is directly internet-exposed: firewall rule {firewall_rule.name} allows ingress
    from 0.0.0.0/0 on {protocol}/{port} and the VM has external IP {external_ip}. Any unauthenticated
    internet actor can attempt to reach the service on that port.'
  derived_from:
  - "<CanReachPort(Internet \u2192 ?vm) edge_id from gcp-firewall-inbound-open>"
  evidence:
    narrative_template: VM {vm.name} has external IP {external_ip} (networkInterfaces[].accessConfigs[].natIP)
      and firewall rule {firewall_rule.name} allows inbound from 0.0.0.0/0 on {protocol}/{port}. No higher-priority
      DENY overrides this allow. The VM is directly internet-reachable.
move · open · esc close