high · 8.7CVE-2026-49259Jul 13, 2026

CVE-2026-49259: NukeViet CMS Stored XSS via Comment Reply Handler

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

A registered user on NukeViet CMS can store a JavaScript payload in their profile name, which executes in any visitor's browser when they click the Reply button on that user's comment, including site

Packagenukeviet/nukeviet
Ecosystemcomposer
Affected< 4.5.09
Fixed in4.6.00

The problem

NukeViet CMS versions 4.x through 4.5.08 embed the commenter's display name directly inside an inline onclick attribute in comment.tpl: onclick="nv_commment_feedback(event, {COMMENT.cid}, '{COMMENT.post_name}')". The display name is sourced from the first_name and last_name profile fields, which are sanitised with HTML numeric character references only.

That encoding is correct for plain HTML contexts but is insufficient inside a JavaScript string literal embedded in an HTML attribute. The browser decodes HTML entities before the JS engine parses the string, so &#039; becomes a live single-quote that terminates the JS string early and lets the remainder execute as code.

Any registered user can set the payload in their profile at /index.php?nv=users&op=editinfo and then post any comment to arm it. With default site settings (no comment moderation, no profile-edit review, unsafe-inline CSP), no additional steps are needed.

Proof of concept

A working proof-of-concept for CVE-2026-49259 in nukeviet/nukeviet, with the exact payload below.

javascript
a');alert(document.cookie);//

Set first_name to the payload above. NukeViet stores it as a&#039;&#41;;alert&#40;document.cookie&#41;;&#x002F;&#x002F;. When a visitor clicks the Reply link on the attacker's comment, the browser decodes HTML entities in the attribute value before handing it to the JS engine, turning &#039; back into a live quote character.

The rendered call becomes nv_commment_feedback(event, 1, 'a');alert(document.cookie);// Tester'), which terminates the string, closes the function call, and executes alert(document.cookie) as a standalone statement. The root cause is CWE-79: HTML numeric character reference encoding is applied in a JavaScript string context where it provides no protection, because the HTML decode step always runs first.

The patch removes post_name from the inline handler entirely, passing only the numeric cid and reading the display name from the already-rendered DOM instead.

The fix

Upgrade to NukeViet 4.6.00 or later. The fix removes {COMMENT.post_name} from the inline onclick handler in themes/default/modules/comment/comment.tpl (both top-level and nested comment positions) so no user-controlled string is interpolated into a JS literal.

If inline passing of the name is required in a custom theme, encode it with PHP's json_encode() rather than HTML entity encoding.

Reporter not attributed.

References: [1][2]

Related research