self_svg_XSS — Self-XSS → Bot-Assisted ATO via SVG upload
Chain an SVG upload, a `blob:` URL, a chat invite and a headless admin helper bot to turn a Self-XSS into full admin account takeover
$750
That's what a company paid for this bug on HackerOne. Here it is, rebuilt for you to find it yourself.
Learn to find this bug
This bug paid $750 on HackerOne.
Create your account and practice real bugs that got paid. Download the environment, find it and learn the exact technique — your path to your first bounty.
hunters training
labs from real hacks
completions
paid out for these bugs
Access to all labs · no commitment · cancel anytime
Hackers who solved it· 8
Objectives
Achievement you'll earn
Solve this lab to unlock this shareable achievement

Community writeups
The checklist I run on every new target
47 checks ordered by cost: first what can get you in trouble, then the cheap stuff, and finally the expensive stuff — which is where the big bounties are. I'll send it to your inbox right now.
Unsubscribe in one click, from any email.
Attack Chain
Root causes (what makes the chain work)
- Unsanitized SVG upload. The server preserves
Content-Type: image/svg+xml
and serves uploads inline (files.ts). - Top-level blob-URL open.
FileAttachment.tsxbuilds a blob URL from the
downloaded file and callswindow.open(blobUrl). A blob URL loaded as a
document inherits the creator's origin, so the SVG's<script>runs inside
NeuroChat's origin. - JWT in
localStorage.auth.tsreturns the token in the JSON response
body and the client stores it inlocalStorage['nc_token']— reachable from
any script running in the origin. - Open chat invites. Any user can invite anyone (including
admin@) into
any chat they own. - Eager admin helper. A headless Chromium bot loads the chat and clicks the
"Open in new tab" button on each attachment, firing the payload.
How to solve
1) Exploration
- Sign in as attacker, upload an SVG that visibly renders (e.g. a simple shape)
- Click Open in new tab — observe it opens on a
blob:URL - Inspect Network tab:
/api/files/:idreturnsContent-Type: image/svg+xml
2) Proof of script exec
Upload an SVG such as:
<svg xmlns="http://www.w3.org/2000/svg" width="120" height="40">
<text y="25">hi</text>
<script>alert(document.domain)</script>
</svg>
Click Open in new tab → alert pops on localhost:1338 → Self-XSS confirmed.
3) Weaponize
Your user id is visible in any decoded JWT (or in /admin if seen, but you are
not admin yet — use atob(token.split('.')[1])). Build an SVG that POSTs your
localStorage to /api/exfil/<id> (see exploit.py).
4) Deliver
Upload the weaponized SVG to a chat. Invite admin@neurochat.ai. The bot polls
every ~15s; it will accept, visit the chat, and click the attachment.
5) Harvest
Open /stolen in the UI (or poll /api/exfil). A capture withemail = admin@neurochat.ai will appear.
6) Takeover
Click Hijack session on that capture (or copy the token intolocalStorage['nc_token']). Browse to /admin → flag.
Or: just run the exploit
python3 exploit.py
Proof of Concept (automated)
exploit.py automates steps 1–6 end-to-end. Typical run:
[1] Login as attacker@neurochat.ai
✓ logged in as #1 (Alex Morgan) · role=user
[2] Create attacker-owned chat
✓ chat id = 5
[3] Craft SVG payload (exfil → /api/exfil/1)
✓ 1.4 KB
[4] Upload dashboard-mockup.svg
✓ mime preserved as image/svg+xml
[5] Post message referencing file
[6] Invite admin@neurochat.ai
[7] Poll /api/exfil for captured admin token
✓ captured admin JWT
[8] Hit /api/admin with stolen JWT
FLAG{e7a15c…}
