# Stored XSS for Grafana dashboard URL

GitLab admin Grafana dashboard URL field accepted javascript: scheme, stored XSS executing in another admin's session via window.opener to steal CSRF token.

- Payout: hidden
- Severity: high
- Program: GitLab
- Found by: xanbanx
- Disclosed: 2022-07-13
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/684268
- Library page: https://bugbountylibrary.com/r/h1%3A684268
- Tags: area:web domain:web impact:ato impact:integrity kind:bounty platform:hackerone sev:high technique:chained vuln:csrf vuln:xss

**Target:** Admin application settings Grafana dashboard URL field
**Root cause:** The Grafana domain setting accepts absolute URLs without validating the scheme, so a javascript: URI is stored and rendered as an anchor href.
**Steps:**
1. As admin open `/admin/application_settings/metrics_and_profiling#js-grafana-settings`
2. Set Grafana domain to `javascript:alert(window.opener.document.location)`
3. Open `Monitoring -> Metrics Dashboard` in admin sidebar
4. Payload executes; use `window.opener` to read CSRF meta token and POST to `/profile/keys`
**How found:** Noticed the Grafana domain field accepts absolute URLs and reasoned the protocol wasn't validated, then tested a javascript: URI and leveraged target=_blank opener access.
**Exploitation:** Malicious admin stores javascript: payload; victim admin clicks the dashboard link (target=_blank), payload runs in opener context, reads `meta[name=csrf-token]`, and POSTs `/profile/keys` to add attacker SSH key for account takeover.
**Escalation:** window.opener bypasses target=_blank isolation to reach victim's authenticated tab and CSRF token, escalating XSS to SSH key injection/ATO.
**Insight:** When a URL field allows absolute addresses, test non-http schemes (javascript:, data:) and check whether target=_blank links retain window.opener, which turns stored XSS into CSRF-token theft.
