# DOM XSS in `fizzy.do` import filename preview enables one-click victim account takeover

Fizzy import page rendered zip filename via innerHTML, letting a crafted filename inject a formaction button that submitted authenticated email-change requests, achieving account takeover.

- Payout: hidden
- Severity: high
- Program: Basecamp
- Found by: xavlimsg
- Disclosed: 2026-04-14
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/3608199
- Library page: https://bugbountylibrary.com/r/h1%3A3608199
- Tags: area:web domain:web impact:ato impact:integrity kind:bounty platform:hackerone sev:high tech:ruby technique:source-review vuln:account-takeover vuln:csrf vuln:xss

**Target:** Web app import filename preview (/account/imports/new)
**Root cause:** The upload preview controller set the selected filename with innerHTML instead of textContent, so a crafted filename was parsed as live HTML inside the authenticated import form containing a valid CSRF token.
**Steps:**
1. Build Fizzy at commit 4211e20a663eb5ad8d4ca3340a1f8d247472c4dc and run with SMTP capture (MailHog).
2. Seed victim owner account and attacker mailbox; authenticate as victim.
3. Create file named `<button formaction=/40002/users/03frq8zae2a7m9cari0v89xua/email_addresses formmethod=post name=email_address value=attacker@example.com>Take over.zip`.
4. As victim open `/account/imports/new` and select the file; injected button renders live.
5. Click injected control; browser POSTs `/40002/users/03frq8zae2a7m9cari0v89xua/email_addresses` with victim session, real CSRF token, `email_address=attacker@example.com`.
6. Retrieve confirmation email in attacker mailbox and visit confirmation URL, submitting the form.
7. Response sets new `session_token` cookie; reuse it to GET `/40002/` and `/40002/users/03frq8zae2a7m9cari0v89xua/edit` (both 200).
**How found:** Code audit of Fizzy main plus live Docker validation; noticed import preview used innerHTML for filename, hypothesized the authenticated form's CSRF token could be leveraged via injected formaction submit control.
**Exploitation:** Attacker sends crafted zip to logged-in victim; one click on import page submits attacker-chosen same-origin authenticated POST using victim session and page CSRF token. Email-change to attacker mailbox yields confirmation link, redeemed to mint fresh victim session, granting full account access. Same primitive also created write-scoped PATs and deleted the account.
**Escalation:** Chained DOM XSS into CSRF-token-bearing form gadget, then email-change confirmation flow to mint a new authenticated session for full account takeover.
**Insight:** When a DOM sink sits inside an authenticated form, injected elements inherit the form's CSRF token and session — look for `formaction`/`formmethod` submit-button injection to convert XSS into arbitrary authenticated POSTs without needing to read the token.
