# GCP Cloud SQL Instance Has Public IP Enabled

> Cloud SQL instances with ipv4Enabled set true are flagged critical by ZopNight rule RC-136: the database endpoint is reachable from the internet, one authorized-networks mistake away from exposure. Detection is proven: the discoverer records the flag in both polarities from instance settings and abstains only when enrichment is missing.

Source: https://zop.dev/integrations/gcp/recommendations/gcp-cloud-sql-instance-has-public-ip-enabled
Updated: 2026-08-19

---

## A database endpoint on the public internet

Enabling public IP on a Cloud SQL instance gives the database a routable IPv4 address that
answers connection attempts from anywhere. The engine's authentication still stands between
an attacker and the data, but that is the *only* thing standing, and it is now doing so
against internet-scale credential stuffing rather than against traffic that first had to get
inside a VPC. ZopNight rates the finding critical because the difference between those two
positions is the difference between defense in depth and a single password.

## Authorized networks are a thinner shield than they look

The standard justification is "we restrict authorized networks." In practice those lists
accumulate: an office CIDR that later gets reassigned, a contractor's home IP added during a
crunch, a `0.0.0.0/0` entry left from debugging. Each entry is a standing grant that
nobody re-reviews, and any future edit can widen it silently. A private-IP instance has no
equivalent failure mode. No list exists whose drift exposes it to the internet.

## Proven from ipv4Enabled, both ways

Detection here is proven, not inferred. The discoverer reads
`settings.ipConfiguration.ipv4Enabled` off the instance's settings proto and writes the
public-access marker as an explicit true or false, in both polarities, on every enrichment. The
rule fires only on the explicit true and abstains when the marker is absent, so an instance
the discoverer never enriched cannot be flagged. The reads ride
`cloudsql.instances.list` under `roles/cloudsql.viewer`, with the bulk sweep under
`roles/cloudasset.viewer`; the finding is informational and nothing modifies the instance.

## List every public instance in a project

```bash
gcloud sql instances list \
  --filter="settings.ipConfiguration.ipv4Enabled=true" \
  --format="table(name,region,ipAddresses[].ipAddress)"
```

## The migration order that avoids breaking clients

Removing the public IP is a hard cutover for anything still using it, so migrate in order:
set up a private services connection in the VPC and enable private IP alongside the public
one; repoint every consumer at the private address; give developers Cloud SQL Auth Proxy for
local access instead of an authorized-network hole; then, with connection logs quiet on the
public address, disable it. The instance keeps running throughout; only the last step
changes what the internet can see, and by then nothing legitimate is arriving that way.
