# Stored but [SELF] XSS in mercantile.wordpress.org

Stored XSS in mercantile.wordpress.org account First/Last Name fields via AngularJS sandbox bypass payload, executing on profile refresh.

- Payout: hidden
- Severity: low
- Program: WordPress
- Found by: codertom
- Disclosed: 2017-05-26
- Write-up quality: 6/10
- Original: https://hackerone.com/reports/222224
- Library page: https://bugbountylibrary.com/r/h1%3A222224
- Tags: area:web domain:web impact:integrity kind:bounty platform:hackerone sev:low technique:source-review vuln:xss

**Target:** Account details edit form (/my-account/edit-account/) on mercantile.wordpress.org
**Root cause:** First/Last Name fields are rendered in an AngularJS context without sanitization; registration filters symbols but post-registration edit does not, allowing AngularJS expression injection that bypasses the sandbox.
**Steps:**
1. Sign up and log in at mercantile.wordpress.org
2. Go to `/my-account/edit-account/`
3. Paste the AngularJS sandbox-bypass payload into `First Name` and `Last Name` and save
4. Refresh the browser; the payload executes (alert/prompt with document.domain)
**How found:** Researcher noted registration restricts symbols but the post-registration edit form does not, then applied a known AngularJS sandbox bypass (credited to PortSwigger research) to the name fields.
**Exploitation:** Attacker stores the AngularJS expression payload in their own profile name fields; on page render AngularJS compiles it, escapes the sandbox via `$evalAsync` AST manipulation, and executes arbitrary JS in the victim's session context.
**Insight:** When a signup form filters special characters, always re-test the post-registration profile edit endpoint — validation is often only applied at creation, not update. AngularJS-rendered profile fields are prime sandbox-bypass targets.

