CVE-2026-47694 Patch Review: Partial fix for AVideo stored XSS in category descriptions
Summary
The patch reduces exploitability of stored XSS in WWBN AVideo category descriptions by changing two rendering paths, but it applies inconsistent output encoding and appears to preserve HTML rendering in one template via a preprocessed field. Based on the provided diff alone, the fix mitigates one sink and changes another sink to a different data source without demonstrating a uniform, root-cause-safe sanitization strategy across all category description renderers.
Analysis
Vulnerability
CVE-2026-47694 describes a stored cross-site scripting issue in WWBN AVideo where authenticated users can place attacker-controlled content into category descriptions, leading to arbitrary JavaScript execution when other users browse affected category views. The core issue shown in the patch diff is unsafe server-side rendering of persisted description data directly into HTML response bodies.
The vulnerable sinks in the supplied patch material are straightforward:
<p style="margin-left: 10%; margin-right: 10%; max-height: 200px; overflow-x: auto;"><?php echo __($category['description']); ?></p>
<div id="categoryDescription<?php echo $duid; ?>" style="display: none;"><?php echo $videos[0]['category_description']; ?></div>In both cases, description content is emitted into the DOM without context-appropriate escaping. Wrapping the first sink in __() does not constitute output encoding for untrusted HTML; it is typically a localization helper, not an HTML sanitizer. As a result, stored payloads such as tag-based or event-handler-based markup could execute when rendered.
Source context: official patch commit, CVE record, and NVD entry.
Patch
The patch modifies two view files referenced by the official commit 6a6ff1f5bff1904f91f612db9f0da083295392b1.
// plugin/Gallery/view/Category.php
<p style="margin-left: 10%; margin-right: 10%; max-height: 200px; overflow-x: auto;"><?php echo $category['description_html']; ?></p>
// plugin/Gallery/view/mainAreaCategory.php
<div id="categoryDescription<?php echo $duid; ?>" style="display: none;"><?php echo textToLink(htmlentities($videos[0]['category_description'])); ?></div>The second change is a conventional mitigation for HTML-body output: htmlentities(...) encodes attacker-controlled markup before insertion, and textToLink(...) appears intended to preserve URL usability by converting plain-text links into anchors after encoding. This materially reduces XSS risk at that sink.
The first change is less conclusive. Replacing $category['description'] with $category['description_html'] may be safe if and only if description_html is generated by a trusted allowlist sanitizer upstream. However, the provided diff does not show where that field is produced, what sanitizer is used, or whether dangerous elements and attributes are removed consistently. Without that evidence, the patch introduces a new trust boundary rather than proving that the root cause is eliminated.
Review
Pros
- Identifies and changes two concrete rendering sinks implicated in the stored XSS path.
- Applies explicit HTML encoding in
plugin/Gallery/view/mainAreaCategory.php, which is the correct defensive primitive for untrusted text rendered into an HTML element body. - The
textToLink(htmlentities(...))ordering suggests an attempt to preserve benign link formatting while neutralizing raw HTML/script injection. - The patch is narrowly scoped and low-risk from a functional perspective in the second template.
Cons
- The remediation is inconsistent across sinks: one template uses encoded text, while another emits a pre-rendered HTML field directly.
- The safety of
$category['description_html']is not demonstrated in the supplied patch. If it is derived from user input without robust allowlist sanitization, stored XSS may remain reachable. - Changing data source names in a view is not, by itself, evidence of root-cause remediation. The actual sanitizer or canonicalization logic is absent from the diff.
- If other templates still render
description,category_description, or related fields without encoding, the vulnerability class may persist elsewhere. htmlentities()defaults can vary by flags/encoding; the patch does not show explicit charset or flags, which is weaker than a project-wide, standardized escaping helper.
Verdict
Partial fix.
The patch clearly mitigates one vulnerable sink by encoding category description text before DOM insertion, but it does not establish a uniform, source-grounded root-cause fix for all category description rendering. The unresolved concern is the direct output of $category['description_html'] in plugin/Gallery/view/Category.php. If that field is sanitized through a strict HTML allowlist elsewhere, this may be sufficient for that path; if not, the application still relies on attacker-influenced HTML reaching the browser.
For a stronger remediation, the codebase should standardize on context-aware output encoding for plain text and use a single vetted HTML sanitization pipeline only where rich text is explicitly required. Engineers should also audit all category-description sinks beyond the two files in the commit and verify the provenance and sanitizer guarantees of description_html. Relevant references: official patch, NVD, CVE.
Recommended Labs
Try this vulnerability pattern yourself with hands-on labs.
- XSS Store.py
Best thematic match for CVE-2026-47694 because the CVE is a stored XSS issue in user-controlled category descriptions. This lab appears explicitly focused on stored XSS behavior, making it useful for practicing output encoding, safe rendering of persisted content, and review of trust boundaries for administrative or authenticated content.
- XSS.php
Strong language-adjacent recommendation because AVideo is a PHP application. This lab is directly relevant for learning how PHP applications should neutralize XSS in rendered content, including server-side output encoding and safer templating patterns applicable to patch review and remediation of category-description rendering flaws.
- Calculator.php
Useful follow-up lab for strengthening defensive instincts in PHP around XSS sinks and unsafe rendering paths. While not as specifically named for stored XSS as the first recommendation, it is still mapped to CWE-79 and helps reinforce patch patterns that matter for persistent user-input scenarios in PHP web apps.