# NukeViet: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Stored XSS in NukeViet comment Reply link: HTML-entity-encoded display name breaks out of an inline JS string, executing in any visitor's browser.

- Payout: Research
- Severity: high
- Program: NukeViet
- Found by: 0xGunrunner
- Disclosed: 2026-07-13
- CVE: CVE-2026-49259
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-w2w5-w2pw-r929
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-w2w5-w2pw-r929
- Tags: area:web domain:web impact:ato impact:privesc kind:research platform:ghsa sev:high tech:php technique:source-review vuln:access-control vuln:xss

**Target:** comment module template inline onclick handler (comment.tpl)
**Root cause:** Profile first_name/last_name are escaped with HTML numeric character references via get_title(...,$specialchars=true), which is insufficient for a JavaScript string literal inside an HTML attribute; browsers decode entities before JS parsing, so ' becomes ' and terminates the string.
**Steps:**
1. Log in as a low-privileged user and open `/index.php?nv=users&op=editinfo`.
2. Set `first_name` to `a');alert(document.domain);//` and save (stored as `a');alert(document.domain);//`).
3. Post any comment (auto_postcomm publishes immediately, no CAPTCHA for logged-in users).
4. Get a visitor/admin to click the Reply link on that comment; rendered handler becomes `nv_commment_feedback(event, 1, 'a');alert(document.domain);// Tester')` and executes.
**How found:** Code review of the comment template spotted `{COMMENT.post_name}` interpolated into an inline onclick JS string; recognized that HTML-entity encoding is decoded before JS parsing, making the sanitizer contextually wrong.
**Exploitation:** Attacker registers, stores payload in profile name fields, posts a comment; any visitor clicking Reply executes attacker JS in their session context, enabling admin action forgery, phishing forms, and exfiltration of non-HttpOnly data to an attacker URL.
**Escalation:** Payload split across both name fields (~200 chars) enables a full data-exfiltration variant navigating the victim to an attacker URL with document.cookie; admin click yields privilege escalation via session hijacking.
**Insight:** When a sanitizer emits HTML numeric character references, check every sink where the value lands inside a JS string literal in an HTML attribute — entity decoding happens before JS parsing, so ' still breaks out; grep templates for `'{VAR}'` inside onclick/onerror handlers.

## Proof of concept (copied exactly from the original report)

**Stored XSS payload in first_name profile field**

```
Set `first_name` to the following value in profile settings (`/index.php?nv=users&op=editinfo`), then post any comment:

a');alert(document.domain);//
```

**Rendered JS showing payload execution**

```
nv_commment_feedback(event, 1, 'a');alert(document.domain);// Tester')

causing `alert(document.domain)` to execute in the visitor's browser context.
```

