---
id: CVE-2026-49259
aliases:
  - GHSA-w2w5-w2pw-r929
title: >-
  NukeViet: Improper Neutralization of Input During Web Page Generation
  ('Cross-site Scripting')
summary: >-
  NukeViet: Improper Neutralization of Input During Web Page Generation
  ('Cross-site Scripting')
severity: high
cvss: 8.7
cwe:
  - CWE-79
vendor: nukeviet
product: nukeviet/nukeviet
ecosystem: composer
affected:
  - nukeviet/nukeviet < 4.5.09
patched:
  - nukeviet/nukeviet 4.6.00
published: '2026-07-13'
updated: '2026-07-13'
source: GHSA
sourceUrl: 'https://github.com/advisories/GHSA-w2w5-w2pw-r929'
references:
  - url: >-
      https://github.com/nukeviet/nukeviet/security/advisories/GHSA-w2w5-w2pw-r929
  - url: 'https://github.com/advisories/GHSA-w2w5-w2pw-r929'
tags:
  - ghsa
  - composer
ingestedAt: '2026-07-13T17:27:58.847Z'
---

## Overview

## Summary

A stored cross-site scripting (XSS) vulnerability exists in NukeViet CMS versions 4.x through 4.5.08. A low-privileged authenticated user can store a JavaScript payload in their profile's display name fields. The payload executes in the browser of any visitor — including administrators — who clicks the **Reply** ("Answer") link on a comment posted by that user.

## Affected Component

The `{COMMENT.post_name}` template variable is interpolated without JavaScript-context escaping into an inline `onclick` handler in both comment block positions:

- `themes/default/modules/comment/comment.tpl` line 27 (top-level comments)
- `themes/default/modules/comment/comment.tpl` line 64 (nested/reply comments)

```html
onclick="nv_commment_feedback(event, {COMMENT.cid}, '{COMMENT.post_name}')"
```

## Root Cause

The `first_name` and `last_name` profile fields are sanitized with HTML numeric character references (`'` → `&#039;`, `(` → `&#40;`, `)` → `&#41;`, `/` → `&#x002F;`) via `Request::_get_title()` with `$specialchars = true`. This encoding is correct for plain HTML attribute and element contexts, but **insufficient for a JavaScript string literal embedded inside an HTML attribute**.

Browsers decode HTML entities in attribute values **before** the JavaScript engine parses the string. As a result, `&#039;` is decoded back to `'`, which terminates the JS string early and allows the remainder of the value to be executed as JavaScript.

The combined display name (`nv_show_name_user(first_name, last_name)`) is what reaches the template, giving an attacker up to ~200 encoded characters across both fields — sufficient for any practical payload.

## Proof of Concept

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

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

The value is stored as `a&#039;&#41;;alert&#40;document.domain&#41;;&#x002F;&#x002F;`.

When a visitor clicks the Reply link on the comment, the browser renders:

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

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

A data-exfiltration variant (split across both name fields) navigates the victim's browser to an attacker-controlled URL carrying `document.cookie` as a query parameter. End-to-end verification was performed using a local listener.

## Exploitation Conditions (default configuration)

| Condition | Default value | Effect |
|---|---|---|
| `captcha_area_comm` | `1` | No CAPTCHA for logged-in users — payload delivery requires no CAPTCHA solve |
| `auto_postcomm` | enabled | Comments are published immediately without moderation |
| `active_editinfo_censor` | `0` | Profile edits take effect immediately without admin review |
| CSP `script-src` | `'unsafe-inline'` | Inline `onclick` handlers execute normally |

Any registered member can set the payload and post a comment with no additional steps.

If `captcha_area_comm` is set to `0`, the `name` field of anonymous comments (`modules/comment/funcs/post.php`) is processed by the same `get_title(..., 1)` call, making exploitation possible without authentication.

## Impact

An attacker with a regular user account can execute arbitrary JavaScript in the browser of any visitor who interacts with the Reply button on their comment, including site administrators.

Practical consequences include:

- **Privilege escalation via admin session hijacking** — forging administrative actions (content modification, account manipulation) in the context of an authenticated admin.
- **Credential phishing** — injecting a fake login form into the page.
- **Data exfiltration** — reading page content and non-`HttpOnly` cookies.

> Note: NukeViet session cookies carry the `HttpOnly` flag, so they are not directly readable via `document.cookie`; however, the above attack vectors remain fully viable.

## Remediation

**Preferred fix:** Remove `post_name` from the inline handler entirely. Pass only `cid` to `nv_commment_feedback` and have the function retrieve the display name from the already-rendered DOM (e.g., the adjacent `<strong class="cm_item">` element).

**Alternative fix:** If the value must be passed inline, encode it with `json_encode($post_name)` (PHP) so that the output is a properly escaped JavaScript string literal, not an HTML-entity-encoded one. HTML numeric character references must not be relied upon for JavaScript string escaping.

As a general note, the result of `get_title(..., $specialchars=true)` is safe for HTML element content and quoted HTML attribute values, but **unsafe when placed inside a JavaScript string literal within an attribute**. Other locations in the codebase using the same pattern should be audited.

## Resources

- OWASP: Cross Site Scripting Prevention — Rule 2: Attribute Encoding is Not Sufficient for JS Contexts
- CWE-79: Improper Neutralization of Input During Web Page Generation
- CWE-116: Improper Encoding or Escaping of Output

## Affected packages

- `nukeviet/nukeviet < 4.5.09`

## Remediation

Upgrade to a patched release:

- `nukeviet/nukeviet 4.6.00`
