Compute Engine VMs with interactive serial console access switched on
What does ZopNight detect here?
Serial console access on a Compute Engine VM bypasses VPC firewalls entirely. Google's global serial gateway accepts connections from any network once serial-port-enable=true is set. ZopNight rule RC-1204 flags instances whose per-instance metadata carries that value, rated high severity. VMs enabled only through project-level metadata are invisible to the check today.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-1204 |
| Category | compliance |
| Severity | high |
| Metric | none — pure configuration read |
| Source | vm_serial_port.go |
Where it applies
A login path your firewall never sees
Interactive serial console access does not travel through your VPC. Connections go to Google’s serial gateway service, which relays them to the VM’s virtual serial port, so firewall rules, private-only networking, and the absence of an external IP all do nothing to stop it. Anyone holding the right IAM permission and a matching SSH key in metadata can reach a login prompt on the machine from any network on the internet. VPC Flow Logs never record the session, because no VPC packet is involved. For a production VM that was deliberately made unreachable from outside, serial-port-enable=true quietly reopens a door on a path most network reviews never look at.
What fires, and the blind spot to know about
Rule RC-1204 fires only when the per-instance serial-port-enable metadata item (mirrored by the discoverer into the resource’s tag sink as serial_port_enabled) is exactly true. Absent, false, or malformed data abstains. The rule therefore proves the per-instance condition, but it carries a known false-negative: GCP also honours serial-port-enable in project-level commonInstanceMetadata, applying it to every VM without an instance override, and the discoverer does not read project metadata. A fleet enabled at project scope produces zero findings today. Until that producer gap closes, audit the project by hand:
gcloud compute project-info describe --project my-project \ --format='value(commonInstanceMetadata.items)' | tr ',' '\n' | grep serial-portShutting the door
Per instance, remove or falsify the key:
gcloud compute instances add-metadata my-vm --zone us-central1-a \ --metadata serial-port-enable=falseFor break-glass access, prefer IAP TCP tunneling: the session is IAM-gated, audited, and does not require the serial gateway.
Kill the whole class at the org
Individual findings recur as long as anyone can set the metadata key. The durable fix is the org policy constraint compute.disableSerialPortAccess, enforced at the organization or folder: with it on, the per-VM setting stops mattering, and exceptions become deliberate policy decisions rather than forgotten debugging leftovers. Serial access is usually enabled during an incident and never turned off afterwards. The org constraint is what breaks that cycle.