← All field notes
gcpvpc service controlsfor security teams

A protected read with no violation: bridging VPC Service Controls

VPC Service Controls stops data leaving even when IAM says yes, but an over-trusted ingress rule and a broad access level can bridge the boundary for valid credentials.

A perimeter is only as strong as its access levels and ingress rules. When a protected read succeeds and there is no perimeter violation in the logs, that absence is itself the signal.

How the attack works

A VPC Service Controls perimeter protects a GCS bucket and a BigQuery dataset of customer exports. But an over-trusted service account sits in the perimeter’s access policy via an ingress rule, and an access level allows a broad corporate CIDR. An attacker who has obtained that service account’s credentials calls the Storage and BigQuery APIs from inside the trusted access level. The perimeter check passes, no violation is logged, and bulk storage.objects.get calls read the exports before a BigQuery extract job moves dataset rows to an attacker-controlled project. In ATT&CK terms this is T1530, Data from Cloud Storage, paired with T1537, Transfer Data to Cloud Account.

Why it works

VPC Service Controls logs a violation when a call crosses the boundary without an allowing rule. A successful protected read with no violation means an ingress rule and access level legitimately bridged the perimeter, even though the identity should never read those objects. The trust, not the credential, is the hole.

How to fix it

Disabling one key does not remove the trust that satisfied the perimeter. Remove the over-trusting ingress rule, narrow the broad access level, add an egress rule denying the external project, and disable the compromised key. That closes the boundary even for valid credentials. VPC firewall rules and renames do nothing, because VPC-SC operates at the API layer. For the root cause, audit every access level and ingress and egress rule for over-broad CIDRs and over-trusted identities, enforce least-trust, and default-deny egress with narrow allowlists. Scope what crossed from Data Access logs and BigQuery job logs, which name the exact objects read and the extract destination.

Practice it

We built this as a GraphLattice Range scenario so security teams can rehearse closing the bridge in a VPC-SC perimeter instead of relying on a key disable.