# Bypassing GCP Org Policy with Custom Metadata

AI Notebooks only validated proxy-user-mail metadata at creation; editing it and restarting re-registered the instance with the Inverting Proxy, granting cross-domain UI access bypassing iam.allowedPolicyMemberDomains.

- Payout: $1,337
- Severity: medium
- Program: Google
- Credited: Kat Traxler
- Disclosed: 2021-09-10
- Write-up quality: 7/10
- Original: https://kattraxler.github.io/gcp/hacking/2021/09/10/gcp-org-policy-bypass-ai-notebooks.html
- Library page: https://bugbountylibrary.com/r/blog%3Akattraxler-github-io-gcp-hacking-2021-09-10-gcp-org-policy-bypass-ai-notebooks-html
- Tags: domain:cloud impact:internal-access impact:privesc kind:bounty platform:blog sev:medium tech:gcp technique:source-review vuln:access-control vuln:auth-bypass vuln:misconfiguration

**Target:** GCP AI Notebooks / Inverting Proxy (googleusercontent.com)
**Root cause:** The Notebooks API validated that the proxy-user-mail user had iam.serviceAccounts.actAs only at notebook creation; on stop/restart re-registration with the Inverting Proxy, no re-validation occurred, so arbitrary users could be authorized via metadata.
**Steps:**
1. Create an AI Notebook in Single-User Mode; note the `proxy-user-mail` metadata tag authorizing the Jupyter UI.
2. Observe the Notebooks API checks the user has Service Account User role only at creation.
3. Modify the instance metadata `proxy-user-mail` to an out-of-domain user (e.g. attacker@external.com).
4. Stop and restart the AI Notebook instance to force re-registration with the Inverting Proxy.
5. Access the Jupyter Notebook web UI as the out-of-domain user, bypassing iam.allowedPolicyMemberDomains.
**How found:** Author reasoned that org policy constraints only govern IAM policy, so any alternate authorization mechanism (custom metadata consumed by the Inverting Proxy) could sidestep it; then noticed the actAs check ran only at creation, not on re-registration after stop/restart.
**Exploitation:** Attacker with ability to set instance metadata changes proxy-user-mail to an external identity, restarts the instance, and the Inverting Proxy then serves the Jupyter UI to that user without any IAM permission on the instance, service account, or org membership.
**Escalation:** Bypasses the iam.allowedPolicyMemberDomains org policy constraint, granting cross-domain resource access that IAM policy alone would forbid.
**Insight:** Org Policy constraints only bind IAM policy — hunt for parallel authorization paths (metadata, proxy headers, side-channel allowlists) that grant access without IAM, and check whether validation runs only at create-time versus on every re-registration/restart.
