# Bypass: Stored-XSS with CSP-bypass via scoped labels' color

Scoped label color from imported GitHub labels wasn't sanitized, yielding stored XSS with CSP bypass on GitLab issue/MR pages.

- Payout: hidden
- Severity: high
- Program: GitLab
- Found by: yvvdwf
- Disclosed: 2023-02-19
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/1693150
- Library page: https://bugbountylibrary.com/r/h1%3A1693150
- Tags: area:web domain:web impact:ato impact:integrity kind:bounty platform:hackerone sev:high tech:rest technique:incomplete-fix technique:source-review vuln:xss

**Target:** GitHub import API / scoped label color rendering
**Root cause:** The fix for the original label-color XSS only sanitized plain labels; the scoped-label rendering path (ee/labels_helper.rb) still emitted the attacker-controlled color into HTML attributes unsanitized.
**Steps:**
1. Create GitLab PAT with api scope and a Premium namespace.
2. Host a dummy GitHub server returning a label named `yvvdwf::label-name` with color `">yvvdwf-label<form class='hidden gl-show-field-errors'><input title='<script>alert(document.domain)</script>'>`.
3. POST to `https://gitlab.com/api/v4/import/github` with `github_hostname` pointing at the dummy server, `target_namespace` set to the premium group.
4. Visit the imported project's `/-/labels` page; `alert(document.domain)` fires.
5. Reference the label in an issue/MR of another project via GitLab-specific references to trigger XSS there too.
**How found:** Reviewed the patch for the prior label-color XSS (15.3.2) and noticed the scoped-label code path in ee/labels_helper.rb was not covered, then tested via a controlled GitHub import server.
**Exploitation:** Attacker controls the GitHub import source, injecting a malicious label color that is stored and rendered on label list, issue and MR pages; CSP is bypassed via the injected form/input markup, executing JS in victims' sessions to call REST APIs on their behalf.
**Escalation:** Chained to fake account takeover by changing victim username then registering it, plus client-side DoS via resource exhaustion.
**Insight:** When a fix sanitizes one rendering path, enumerate sibling code paths (here scoped vs plain labels) that format the same attacker-controlled field; import-from-external-source features let you supply arbitrary field values.
