# WWBN AVideo: Stored XSS via autoEvalCodeOnHTML Bypass in MessageSQLite WebSocket Handler (CVE-2026-43874 Bypass)

AVideo's MessageSQLite WebSocket handler only strips autoEvalCodeOnHTML from msg, so placing it in the json key bypasses sanitization and yields stored XSS.

- Payout: Research
- Severity: high
- Program: AVideo
- Found by: oduoke567
- Disclosed: 2026-06-04
- CVE: CVE-2026-49279
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-2fhx-q92v-5fhv
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-2fhx-q92v-5fhv
- Tags: area:web domain:web impact:ato impact:integrity kind:research platform:ghsa sev:high tech:php tech:websocket technique:incomplete-fix technique:source-review vuln:xss

**Target:** WebSocket messaging handler (plugin/YPTSocket/MessageSQLite.php)
**Root cause:** The incomplete fix only unsets autoEvalCodeOnHTML from $json['msg'], but msgToResourceId() prefers $msg['json'] when non-empty, so the payload in the json key is never sanitized.
**Steps:**
1. Connect to `wss://TARGET/plugin/YPTSocket/server.php?token=USER_TOKEN` as an authenticated user.
2. Send a JSON message with a decoy `msg: "Hello"` and the payload in `json: {autoEvalCodeOnHTML: "alert('XSS')"}`, plus `to_users_id` and `resourceId`.
3. Sanitizer at lines 268-271 only strips `$json['msg']['autoEvalCodeOnHTML']`, leaving `json` untouched.
4. `msgToResourceId()` takes the `!empty($msg['json'])` branch and delivers the payload to the victim's client.
5. Victim's WebSocket client evaluates the payload via autoEvalCodeOnHTML.
**How found:** Compared the shallow sanitization in MessageSQLite.php against the recursive removeAutoEvalCodeOnHTMLRecursive() used in Message.php and MessageSQLiteV2.php, then noticed msgToResourceId() prioritizes $msg['json'] over the sanitized $msg['msg'] path.
**Exploitation:** Authenticated attacker sends a crafted WebSocket message to a victim user ID; the unsanitized json key is delivered and evaluated in the victim's browser, enabling session cookie/token theft and account takeover.
**Escalation:** Chain with CSRF to perform admin actions as the victim; session hijacking leads to account takeover.
**Insight:** When a fix strips a dangerous key from one field, check every sibling field the same sink reads from — here msgToResourceId() prefers json over msg, so the sanitized path is a decoy; diff sibling handlers (Message.php, MessageSQLiteV2.php) to spot the incomplete fix.

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

**WebSocket message with payload in json key**

```
const ws = new WebSocket('wss://TARGET/plugin/YPTSocket/server.php?token=USER_TOKEN');

ws.onopen = () => {
  ws.send(JSON.stringify({
    msg: "Hello",                               // sanitized path — decoy
    json: {autoEvalCodeOnHTML: "alert('XSS')"},  // unsanitized path — payload
    to_users_id: VICTIM_USER_ID,
    resourceId: RESOURCE_ID
  }));
};
// Victim's client evaluates alert('XSS') via autoEvalCodeOnHTML mechanism
```

