The server-side mitigation for the YPTSocket autoEvalCodeOnHTML eval sink (prior advisory GHSA-gph2-j4c9-vhhr, commit c08694bf6) only strips the payload when it sits under $json['msg'], but the relay function msgToResourceId() selects the outbound message from $msg['json'] before $msg['msg']. An unauthenticated attacker can obtain a WebSocket token from plugin/YPTSocket/getWebSocket.json.php, connect to the WebSocket server, and send a message with autoEvalCodeOnHTML nested under a top-level json field — the strip branch is skipped, the relay delivers the payload verbatim to any logged-in user identified by to_users_id, and the client script runs it through eval().
plugin/YPTSocket/getWebSocket.json.php (lines 1–21) issues a valid WebSocket token to any caller, with no authentication or CSRF check:
$obj->webSocketToken = getEncryptedInfo(0);
$obj->webSocketURL = YPTSocket::getWebSocketURL();
die(json_encode($obj));
getEncryptedInfo() defaults to sentFrom = 'browser' and a non-CLI flag (plugin/YPTSocket/functions.php:3-47), so a token minted for an anonymous browser client will cause the strip branch below to run — which is exactly what we want to audit.
plugin/YPTSocket/Message.php:236-247:
// Strip eval-able fields from browser/guest messages.
if (empty($msgObj->isCommandLineInterface) && ($msgObj->sentFrom ?? '') !== 'php') {
if (is_array($json['msg'] ?? null)) {
unset($json['msg']['autoEvalCodeOnHTML']); // <-- only strips $json['msg']
}
if (isset($json['callback']) && !preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', (string)$json['callback'])) {
unset($json['callback']);
}
}
If the incoming $json['msg'] is a scalar (e.g. the string "x"), is_array(...) is false and the strip is skipped entirely. Any eval-able content that lives elsewhere in $json...
Exploitability
AV:NAC:LPR:NUI:NScope
S:CImpact
C:LI:LA:N7.2/CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N