Shared security patch analysis results
AI Used: claude_cli haiku--- cache/mybb_mybb_1807/admin/inc/class_page.php 2025-12-06 11:32:55.082119266 +0000+++ cache/mybb_mybb_1808/admin/inc/class_page.php 2025-12-06 11:32:55.894171701 +0000@@ -142,7 +142,8 @@ echo "<body>\n"; echo "<div id=\"container\">\n"; echo " <div id=\"logo\"><h1><span class=\"invisible\">{$lang->mybb_admin_cp}</span></h1></div>\n";- echo " <div id=\"welcome\"><span class=\"logged_in_as\">{$lang->logged_in_as} <a href=\"index.php?module=user-users&action=edit&uid={$mybb->user['uid']}\" class=\"username\">{$mybb->user['username']}</a></span> | <a href=\"{$mybb->settings['bburl']}\" target=\"_blank\" class=\"forum\">{$lang->view_board}</a> | <a href=\"index.php?action=logout&my_post_key={$mybb->post_code}\" class=\"logout\">{$lang->logout}</a></div>\n";+ $username = htmlspecialchars_uni($mybb->user['username']);+ echo " <div id=\"welcome\"><span class=\"logged_in_as\">{$lang->logged_in_as} <a href=\"index.php?module=user-users&action=edit&uid={$mybb->user['uid']}\" class=\"username\">{$username}</a></span> | <a href=\"{$mybb->settings['bburl']}\" target=\"_blank\" class=\"forum\">{$lang->view_board}</a> | <a href=\"index.php?action=logout&my_post_key={$mybb->post_code}\" class=\"logout\">{$lang->logout}</a></div>\n"; echo $this->_build_menu(); echo " <div id=\"page\">\n"; echo " <div id=\"left_menu\">\n";@@ -224,7 +225,7 @@ echo " <br style=\"clear: both;\" />"; echo " <br style=\"clear: both;\" />"; echo " </div>\n";- echo "<div id=\"footer\"><p class=\"generation\">".$lang->sprintf($lang->generated_in, $totaltime, $debuglink, $querycount, $memory_usage)."</p><p class=\"powered\">Powered By <a href=\"http://www.mybb.com/\" target=\"_blank\">MyBB</a>, © 2002-".COPY_YEAR." <a href=\"http://www.mybb.com/\" target=\"_blank\">MyBB Group</a>.</p></div>\n";+ echo "<div id=\"footer\"><p class=\"generation\">".$lang->sprintf($lang->generated_in, $totaltime, $debuglink, $querycount, $memory_usage)."</p><p class=\"powered\">Powered By <a href=\"https://mybb.com/\" target=\"_blank\">MyBB</a>, © 2002-".COPY_YEAR." <a href=\"https://mybb.com/\" target=\"_blank\">MyBB Group</a>.</p></div>\n"; if($mybb->debug_mode) { echo $db->explain;@@ -902,11 +903,11 @@ if($smilies) { if($mybb->settings['smilieinserter'] && $mybb->settings['smilieinsertercols'] && $mybb->settings['smilieinsertertot'])- { + { $emoticon = ",emoticon"; } $emoticons_enabled = "true";- + if(!$smiliecount) { $smilie_cache = $cache->read("smilies");@@ -939,7 +940,7 @@ { $finds = explode("\n", $smilie['find']); $finds_count = count($finds);- + // Only show the first text to replace in the box $find = str_replace(array('\\', '"'), array('\\\\', '\"'), htmlspecialchars_uni($finds[0])); $image = str_replace(array('\\', '"'), array('\\\\', '\"'), htmlspecialchars_uni($smilie['image']));@@ -950,7 +951,7 @@ if(!$mybb->settings['smilieinserter'] || !$mybb->settings['smilieinsertercols'] || !$mybb->settings['smilieinsertertot'] || !$smilie['showclickable']) {- $hiddensmilies .= '"'.$find.'": "'.$image.'",'; + $hiddensmilies .= '"'.$find.'": "'.$image.'",'; } elseif($i < $mybb->settings['smilieinsertertot']) {
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - admin/inc/class_page.php - Line 145
Old Code:
```php
echo " <div id=\"welcome\"><span class=\"logged_in_as\">{$lang->logged_in_as} <a href=\"index.php?module=user-users&action=edit&uid={$mybb->user['uid']}\" class=\"username\">{$mybb->user['username']}</a></span> | <a href=\"{$mybb->settings['bburl']}\" target=\"_blank\" class=\"forum\">{$lang->view_board}</a> | <a href=\"index.php?action=logout&my_post_key={$mybb->post_code}\" class=\"logout\">{$lang->logout}</a></div>\n";
```
Fixed Code:
```php
$username = htmlspecialchars_uni($mybb->user['username']);
echo " <div id=\"welcome\"><span class=\"logged_in_as\">{$lang->logged_in_as} <a href=\"index.php?module=user-users&action=edit&uid={$mybb->user['uid']}\" class=\"username\">{$username}</a></span> | <a href=\"{$mybb->settings['bburl']}\" target=\"_blank\" class=\"forum\">{$lang->view_board}</a> | <a href=\"index.php?action=logout&my_post_key={$mybb->post_code}\" class=\"logout\">{$lang->logout}</a></div>\n";
```
Explanation:
The username stored in `$mybb->user['username']` is user-controlled data that was directly embedded in HTML output without sanitization. An attacker could inject malicious JavaScript or HTML through their username field, which would execute in the context of the admin panel for any administrator viewing the welcome section. The fix applies `htmlspecialchars_uni()` to escape the username before output, preventing XSS payload execution.
---
Vulnerability Existed: no
Insecure Protocol - CWE-295 - admin/inc/class_page.php - Line 228
Old Code:
```php
echo "<div id=\"footer\"><p class=\"generation\">".$lang->sprintf($lang->generated_in, $totaltime, $debuglink, $querycount, $memory_usage)."</p><p class=\"powered\">Powered By <a href=\"http://www.mybb.com/\" target=\"_blank\">MyBB</a>, © 2002-".COPY_YEAR." <a href=\"http://www.mybb.com/\" target=\"_blank\">MyBB Group</a>.</p></div>\n";
```
Fixed Code:
```php
echo "<div id=\"footer\"><p class=\"generation\">".$lang->sprintf($lang->generated_in, $totaltime, $debuglink, $querycount, $memory_usage)."</p><p class=\"powered\">Powered By <a href=\"https://mybb.com/\" target=\"_blank\">MyBB</a>, © 2002-".COPY_YEAR." <a href=\"https://mybb.com/\" target=\"_blank\">MyBB Group</a>.</p></div>\n";
```
Explanation:
While not a direct code vulnerability, this change upgrades HTTP links to HTTPS for external resources (mybb.com). The change improves security by ensuring users are directed to secure connections when visiting the MyBB website from the admin panel, and also updates the URL to the current domain. This is a security hardening measure rather than a vulnerability fix.
---
Vulnerability Existed: no
[Whitespace/Code Quality Changes] - admin/inc/class_page.php - Lines 906, 908, 943, 954
Explanation:
The remaining changes in the diff are purely whitespace corrections (trailing spaces and indentation fixes). These are code quality improvements with no security implications.
--- cache/mybb_mybb_1807/admin/inc/functions_themes.php 2025-12-06 11:32:55.082119266 +0000+++ cache/mybb_mybb_1808/admin/inc/functions_themes.php 2025-12-06 11:32:55.894171701 +0000@@ -388,7 +388,7 @@ { global $mybb; - $filename = str_replace('/', '', $filename);+ $filename = basename($filename); $tid = (int) $tid; $theme_directory = "cache/themes/theme{$tid}";
Vulnerability Existed: yes
TRUE POSITIVE
Path Traversal - CWE-22 - admin/inc/functions_themes.php lines 391
Old Code:
```php
$filename = str_replace('/', '', $filename);
```
Fixed Code:
```php
$filename = basename($filename);
```
Explanation:
The original code attempted to prevent path traversal by simply removing forward slashes from the filename using `str_replace('/', '', $filename)`. This is an inadequate security fix because:
1. **Incomplete filtering**: The code only removes forward slashes (`/`) but doesn't handle backslashes (`\`), which can also be used for path traversal on Windows systems or in certain PHP contexts.
2. **Ineffective against encoded traversal**: Attackers could use URL-encoded slashes (`%2f`) or other bypass techniques that `str_replace` wouldn't catch.
3. **Still vulnerable to directory traversal**: An attacker could potentially use sequences like `..` combined with other techniques to escape the intended directory.
The fix using `basename($filename)` is significantly more secure because:
- `basename()` is a built-in PHP function specifically designed to extract only the filename component from a path
- It strips all directory information, including both forward slashes and backslashes
- It properly handles various edge cases and platform-specific path separators
- It's the recommended approach for isolating filenames from user input
This is a proper security fix that addresses the path traversal vulnerability by using the appropriate PHP function for filename extraction rather than attempting fragile string filtering.
--- cache/mybb_mybb_1807/admin/inc/functions_view_manager.php 2025-12-06 11:32:55.082119266 +0000+++ cache/mybb_mybb_1808/admin/inc/functions_view_manager.php 2025-12-06 11:32:55.894171701 +0000@@ -575,7 +575,8 @@ $view_type = "group"; if($view['username']) {- $created = "<br /><small>{$lang->created_by} {$view['username']}</small>";+ $username = htmlspecialchars_uni($view['username']);+ $created = "<br /><small>{$lang->created_by} {$username}</small>"; } } else
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - admin/inc/functions_view_manager.php [Line 578]
Old Code:
```php
$created = "<br /><small>{$lang->created_by} {$view['username']}</small>";
```
Fixed Code:
```php
$username = htmlspecialchars_uni($view['username']);
$created = "<br /><small>{$lang->created_by} {$username}</small>";
```
Explanation:
The original code directly interpolated `$view['username']` into HTML output without escaping. If the username contains special characters or HTML/JavaScript, it could be rendered as-is in the browser, allowing an attacker to inject malicious scripts. The fix applies `htmlspecialchars_uni()` to properly escape the username before inserting it into the HTML string, preventing XSS attacks. This is a standard and appropriate mitigation for reflected/stored XSS vulnerabilities in web applications.
--- cache/mybb_mybb_1807/admin/index.php 2025-12-06 11:32:55.082119266 +0000+++ cache/mybb_mybb_1808/admin/index.php 2025-12-06 11:32:55.894171701 +0000@@ -11,8 +11,9 @@ define("IN_MYBB", 1); define("IN_ADMINCP", 1); -// Here you can change how much of an Admin CP IP address must match in a previous session for the user is validated (defaults to 3 which matches a.b.c)+// Here you can change how much of an Admin CP IP address must match in a previous session for the user is validated (e.g. 3 means a.b.c need to match) define("ADMIN_IP_SEGMENTS", 0);+define("ADMIN_IPV6_SEGMENTS", 0); require_once dirname(dirname(__FILE__))."/inc/init.php"; @@ -386,7 +387,7 @@ $mybb->user = get_user($admin_session['uid']); // Login key has changed - force logout- if(!$mybb->user['uid'] || $mybb->user['loginkey'] != $admin_session['loginkey'])+ if(!$mybb->user['uid'] || $mybb->user['loginkey'] !== $admin_session['loginkey']) { unset($mybb->user); }@@ -400,10 +401,10 @@ unset($mybb->user); } // If IP matching is set - check IP address against the session IP- else if(ADMIN_IP_SEGMENTS > 0)+ else if(ADMIN_IP_SEGMENTS > 0 && strpos($ip_address, ':') === false) { $exploded_ip = explode(".", $ip_address);- $exploded_admin_ip = explode(".", $admin_session['ip']);+ $exploded_admin_ip = explode(".", my_inet_ntop($admin_session['ip'])); $matches = 0; $valid_ip = false; for($i = 0; $i < ADMIN_IP_SEGMENTS; ++$i)@@ -426,6 +427,38 @@ unset($mybb->user); } }+ else if(ADMIN_IPV6_SEGMENTS > 0 && strpos($ip_address, ':') !== false)+ {+ // Expand IPv6 addresses+ $hex = unpack("H*hex", my_inet_pton($ip_address)); + $expanded_ip = substr(preg_replace("/([A-f0-9]{4})/", "$1:", $hex['hex']), 0, -1);+ $hex_admin = unpack("H*hex", $admin_session['ip']); + $expanded_admin_ip = substr(preg_replace("/([A-f0-9]{4})/", "$1:", $hex_admin['hex']), 0, -1);++ $exploded_ip = explode(":", $expanded_ip);+ $exploded_admin_ip = explode(":", $expanded_admin_ip);+ $matches = 0;+ $valid_ip = false;+ for($i = 0; $i < ADMIN_IPV6_SEGMENTS; ++$i)+ {+ if($exploded_ip[$i] == $exploded_admin_ip[$i])+ {+ ++$matches;+ }+ if($matches == ADMIN_IPV6_SEGMENTS)+ {+ $valid_ip = true;+ break;+ }+ }++ // IP doesn't match properly - show message on logon screen+ if(!$valid_ip)+ {+ $login_message = $lang->error_invalid_ip;+ unset($mybb->user);+ }+ } } } }@@ -755,7 +788,7 @@ if($post_verify == true) { // If the post key does not match we switch the action to GET and set a message to show the user- if(!isset($mybb->input['my_post_key']) || $mybb->post_code != $mybb->input['my_post_key'])+ if(!isset($mybb->input['my_post_key']) || $mybb->post_code !== $mybb->input['my_post_key']) { $mybb->request_method = "get"; $page->show_post_verify_error = true;
Analyzing the provided code diff for security vulnerabilities...
---
**Vulnerability 1:**
Vulnerability Existed: yes
TRUE POSITIVE
Timing Attack / Information Disclosure - CWE-208 - admin/index.php Line 390
```php
if(!$mybb->user['uid'] || $mybb->user['loginkey'] != $admin_session['loginkey'])
```
```php
if(!$mybb->user['uid'] || $mybb->user['loginkey'] !== $admin_session['loginkey'])
```
Explanation:
The original code used loose comparison operator (`!=`) for comparing login keys. This was changed to strict comparison (`!==`). While this isn't a direct timing attack vulnerability, loose comparison can allow type juggling bypasses. The strict comparison prevents potential security issues where different types could be considered equal (e.g., "0" == false). This is a security hardening fix.
---
**Vulnerability 2:**
Vulnerability Existed: yes
TRUE POSITIVE
Improper Validation - CWE-20 - admin/index.php Line 404
```php
else if(ADMIN_IP_SEGMENTS > 0)
{
$exploded_ip = explode(".", $ip_address);
$exploded_admin_ip = explode(".", $admin_session['ip']);
```
```php
else if(ADMIN_IP_SEGMENTS > 0 && strpos($ip_address, ':') === false)
{
$exploded_ip = explode(".", $ip_address);
$exploded_admin_ip = explode(".", my_inet_ntop($admin_session['ip']));
```
Explanation:
The original code attempted IPv4 address validation without checking if the IP was actually IPv4 format. IPv6 addresses contain colons and would fail when split by dots, causing validation bypass. The fix adds a check `strpos($ip_address, ':') === false` to ensure only IPv4 addresses are processed by this logic block, and properly converts the stored IP using `my_inet_ntop()` before splitting. This prevents IPv6 addresses from bypassing IP validation checks.
---
**Vulnerability 3:**
Vulnerability Existed: yes
TRUE POSITIVE
Improper Validation - CWE-20 - admin/index.php Line 404-427 (New Code Addition)
```php
[IPv6 handling was missing entirely]
```
```php
else if(ADMIN_IPV6_SEGMENTS > 0 && strpos($ip_address, ':') !== false)
{
// New IPv6 validation block added
$hex = unpack("H*hex", my_inet_pton($ip_address));
// ... IPv6 comparison logic
}
```
Explanation:
The original code had no IPv6 support for admin IP validation. IPv6 addresses were either not validated or would fail validation entirely, creating a potential security bypass where IPv6-connected administrators could not be properly validated. The fix adds comprehensive IPv6 support with proper address expansion and segment matching, closing this validation gap.
---
**Vulnerability 4:**
Vulnerability Existed: yes
FALSE POSITIVE
Timing Attack / Information Disclosure - CWE-208 - admin/index.php Line 791
```php
if(!isset($mybb->input['my_post_key']) || $mybb->post_code != $mybb->input['my_post_key'])
```
```php
if(!isset($mybb->input['my_post_key']) || $mybb->post_code !== $mybb->input['my_post_key'])
```
Explanation:
Similar to Vulnerability 1, this changes loose comparison (`!=`) to strict comparison (`!==`) for CSRF token validation. The loose comparison could allow type juggling attacks where different types are treated as equal. For security-critical operations like CSRF protection, strict comparison prevents potential bypass scenarios.
--- cache/mybb_mybb_1807/admin/modules/config/attachment_types.php 2025-12-06 11:32:55.110121074 +0000+++ cache/mybb_mybb_1808/admin/modules/config/attachment_types.php 2025-12-06 11:32:55.906172476 +0000@@ -46,6 +46,35 @@ $mybb->input['extension'] = substr($mybb->input['extension'], 1); } + foreach(array('groups', 'forums') as $key)+ {+ if($mybb->input[$key] == 'all')+ {+ $mybb->input[$key] = -1;+ }+ elseif($mybb->input[$key] == 'custom')+ {+ if(isset($mybb->input['select'][$key]) && is_array($mybb->input['select'][$key]))+ {+ foreach($mybb->input['select'][$key] as &$val)+ {+ $val = (int)$val;+ }+ unset($val);++ $mybb->input[$key] = implode(',', (array)$mybb->input['select'][$key]);+ }+ else+ {+ $mybb->input[$key] = '';+ }+ }+ else+ {+ $mybb->input[$key] = '';+ }+ }+ $maxsize = $mybb->get_input('maxsize', MyBB::INPUT_INT); if($maxsize == 0)@@ -58,7 +87,11 @@ "mimetype" => $db->escape_string($mybb->input['mimetype']), "extension" => $db->escape_string($mybb->input['extension']), "maxsize" => $maxsize,- "icon" => $db->escape_string($mybb->input['icon'])+ "icon" => $db->escape_string($mybb->input['icon']),+ 'enabled' => $mybb->get_input('enabled', MyBB::INPUT_INT),+ 'groups' => $db->escape_string($mybb->get_input('groups')),+ 'forums' => $db->escape_string($mybb->get_input('forums')),+ 'avatarfile' => $mybb->get_input('avatarfile', MyBB::INPUT_INT) ); $atid = $db->insert_query("attachtypes", $new_type);@@ -95,6 +128,32 @@ if($errors) {+ switch($mybb->input['groups'])+ {+ case 'all':+ $mybb->input['groups'] = -1;+ break;+ case 'custom':+ $mybb->input['groups'] = implode(',', (array)$mybb->input['select']['groups']);+ break;+ default:+ $mybb->input['groups'] = '';+ break;+ }++ switch($mybb->input['forums'])+ {+ case 'all':+ $mybb->input['forums'] = -1;+ break;+ case 'custom':+ $mybb->input['forums'] = implode(',', (array)$mybb->input['select']['forums']);+ break;+ default:+ $mybb->input['forums'] = '';+ break;+ }+ $page->output_inline_error($errors); } else@@ -103,6 +162,16 @@ $mybb->input['icon'] = "images/attachtypes/"; } + if(empty($mybb->input['groups']))+ {+ $mybb->input['groups'] = '';+ }++ if(empty($mybb->input['forums']))+ {+ $mybb->input['forums'] = '';+ }+ // PHP settings $upload_max_filesize = @ini_get('upload_max_filesize'); $post_max_size = @ini_get('post_max_size');@@ -120,12 +189,106 @@ } } + $selected_values = '';+ if($mybb->input['groups'] != '' && $mybb->input['groups'] != -1)+ {+ $selected_values = explode(',', $mybb->get_input('groups'));++ foreach($selected_values as &$value)+ {+ $value = (int)$value;+ }+ unset($value);+ }++ $group_checked = array('all' => '', 'custom' => '', 'none' => '');+ if($mybb->input['groups'] == -1)+ {+ $group_checked['all'] = 'checked="checked"';+ }+ elseif($mybb->input['groups'] != '')+ {+ $group_checked['custom'] = 'checked="checked"';+ }+ else+ {+ $group_checked['none'] = 'checked="checked"';+ }++ print_selection_javascript();++ $groups_select_code = "+ <dl style=\"margin-top: 0; margin-bottom: 0; width: 100%\">+ <dt><label style=\"display: block;\"><input type=\"radio\" name=\"groups\" value=\"all\" {$group_checked['all']} class=\"groups_forums_groups_check\" onclick=\"checkAction('groups');\" style=\"vertical-align: middle;\" /> <strong>{$lang->all_groups}</strong></label></dt>+ <dt><label style=\"display: block;\"><input type=\"radio\" name=\"groups\" value=\"custom\" {$group_checked['custom']} class=\"groups_forums_groups_check\" onclick=\"checkAction('groups');\" style=\"vertical-align: middle;\" /> <strong>{$lang->select_groups}</strong></label></dt>+ <dd style=\"margin-top: 4px;\" id=\"groups_forums_groups_custom\" class=\"groups_forums_groups\">+ <table cellpadding=\"4\">+ <tr>+ <td valign=\"top\"><small>{$lang->groups_colon}</small></td>+ <td>".$form->generate_group_select('select[groups][]', $selected_values, array('id' => 'groups', 'multiple' => true, 'size' => 5))."</td>+ </tr>+ </table>+ </dd>+ <dt><label style=\"display: block;\"><input type=\"radio\" name=\"groups\" value=\"none\" {$group_checked['none']} class=\"groups_forums_groups_check\" onclick=\"checkAction('groups');\" style=\"vertical-align: middle;\" /> <strong>{$lang->none}</strong></label></dt>+ </dl>+ <script type=\"text/javascript\">+ checkAction('groups');+ </script>";++ $selected_values = '';+ if($mybb->input['forums'] != '' && $mybb->input['forums'] != -1)+ {+ $selected_values = explode(',', $mybb->get_input('forums'));++ foreach($selected_values as &$value)+ {+ $value = (int)$value;+ }+ unset($value);+ }++ $forum_checked = array('all' => '', 'custom' => '', 'none' => '');+ if($mybb->input['forums'] == -1)+ {+ $forum_checked['all'] = 'checked="checked"';+ }+ elseif($mybb->input['forums'] != '')+ {+ $forum_checked['custom'] = 'checked="checked"';+ }+ else+ {+ $forum_checked['none'] = 'checked="checked"';+ }++ $forums_select_code = "+ <dl style=\"margin-top: 0; margin-bottom: 0; width: 100%\">+ <dt><label style=\"display: block;\"><input type=\"radio\" name=\"forums\" value=\"all\" {$forum_checked['all']} class=\"forums_forums_groups_check\" onclick=\"checkAction('forums');\" style=\"vertical-align: middle;\" /> <strong>{$lang->all_forums}</strong></label></dt>+ <dt><label style=\"display: block;\"><input type=\"radio\" name=\"forums\" value=\"custom\" {$forum_checked['custom']} class=\"forums_forums_groups_check\" onclick=\"checkAction('forums');\" style=\"vertical-align: middle;\" /> <strong>{$lang->select_forums}</strong></label></dt>+ <dd style=\"margin-top: 4px;\" id=\"forums_forums_groups_custom\" class=\"forums_forums_groups\">+ <table cellpadding=\"4\">+ <tr>+ <td valign=\"top\"><small>{$lang->forums_colon}</small></td>+ <td>".$form->generate_forum_select('select[forums][]', $selected_values, array('id' => 'forums', 'multiple' => true, 'size' => 5))."</td>+ </tr>+ </table>+ </dd>+ <dt><label style=\"display: block;\"><input type=\"radio\" name=\"forums\" value=\"none\" {$forum_checked['none']} class=\"forums_forums_groups_check\" onclick=\"checkAction('forums');\" style=\"vertical-align: middle;\" /> <strong>{$lang->none}</strong></label></dt>+ </dl>+ <script type=\"text/javascript\">+ checkAction('forums');+ </script>";+ $form_container = new FormContainer($lang->add_new_attachment_type); $form_container->output_row($lang->name, $lang->name_desc, $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); $form_container->output_row($lang->file_extension." <em>*</em>", $lang->file_extension_desc, $form->generate_text_box('extension', $mybb->input['extension'], array('id' => 'extension')), 'extension'); $form_container->output_row($lang->mime_type." <em>*</em>", $lang->mime_type_desc, $form->generate_text_box('mimetype', $mybb->input['mimetype'], array('id' => 'mimetype')), 'mimetype'); $form_container->output_row($lang->maximum_file_size, $lang->maximum_file_size_desc.$limit_string, $form->generate_numeric_field('maxsize', $mybb->input['maxsize'], array('id' => 'maxsize', 'min' => 0)), 'maxsize'); $form_container->output_row($lang->attachment_icon, $lang->attachment_icon_desc, $form->generate_text_box('icon', $mybb->input['icon'], array('id' => 'icon')), 'icon');+ $form_container->output_row($lang->enabled, '', $form->generate_yes_no_radio('enabled', $mybb->input['enabled']), 'enabled');+ $form_container->output_row($lang->available_to_groups, '', $groups_select_code, '', array(), array('id' => 'row_groups'));+ $form_container->output_row($lang->available_in_forums, '', $forums_select_code, '', array(), array('id' => 'row_forums'));+ $form_container->output_row($lang->avatar_file, $lang->avatar_file_desc, $form->generate_yes_no_radio('avatarfile', $mybb->input['avatarfile']), 'avatarfile'); $form_container->end(); @@ -174,12 +337,45 @@ $mybb->input['extension'] = substr($mybb->input['extension'], 1); } + foreach(array('groups', 'forums') as $key)+ {+ if($mybb->input[$key] == 'all')+ {+ $mybb->input[$key] = -1;+ }+ elseif($mybb->input[$key] == 'custom')+ {+ if(isset($mybb->input['select'][$key]) && is_array($mybb->input['select'][$key]))+ {+ foreach($mybb->input['select'][$key] as &$val)+ {+ $val = (int)$val;+ }+ unset($val);++ $mybb->input[$key] = implode(',', (array)$mybb->input['select'][$key]);+ }+ else+ {+ $mybb->input[$key] = '';+ }+ }+ else+ {+ $mybb->input[$key] = '';+ }+ }+ $updated_type = array( "name" => $db->escape_string($mybb->input['name']), "mimetype" => $db->escape_string($mybb->input['mimetype']), "extension" => $db->escape_string($mybb->input['extension']), "maxsize" => $mybb->get_input('maxsize', MyBB::INPUT_INT),- "icon" => $db->escape_string($mybb->input['icon'])+ "icon" => $db->escape_string($mybb->input['icon']),+ 'enabled' => $mybb->get_input('enabled', MyBB::INPUT_INT),+ 'groups' => $db->escape_string($mybb->get_input('groups')),+ 'forums' => $db->escape_string($mybb->get_input('forums')),+ 'avatarfile' => $mybb->get_input('avatarfile', MyBB::INPUT_INT) ); $plugins->run_hooks("admin_config_attachment_types_edit_commit");@@ -211,6 +407,32 @@ if($errors) {+ switch($mybb->input['groups'])+ {+ case 'all':+ $mybb->input['groups'] = -1;+ break;+ case 'custom':+ $mybb->input['groups'] = implode(',', (array)$mybb->input['select']['groups']);+ break;+ default:+ $mybb->input['groups'] = '';+ break;+ }++ switch($mybb->input['forums'])+ {+ case 'all':+ $mybb->input['forums'] = -1;+ break;+ case 'custom':+ $mybb->input['forums'] = implode(',', (array)$mybb->input['select']['forums']);+ break;+ default:+ $mybb->input['forums'] = '';+ break;+ }+ $page->output_inline_error($errors); } else@@ -218,6 +440,16 @@ $mybb->input = array_merge($mybb->input, $attachment_type); } + if(empty($mybb->input['groups']))+ {+ $mybb->input['groups'] = '';+ }++ if(empty($mybb->input['forums']))+ {+ $mybb->input['forums'] = '';+ }+ // PHP settings $upload_max_filesize = @ini_get('upload_max_filesize'); $post_max_size = @ini_get('post_max_size');@@ -235,12 +467,106 @@ } } + $selected_values = '';+ if($mybb->input['groups'] != '' && $mybb->input['groups'] != -1)+ {+ $selected_values = explode(',', $mybb->get_input('groups'));++ foreach($selected_values as &$value)+ {+ $value = (int)$value;+ }+ unset($value);+ }++ $group_checked = array('all' => '', 'custom' => '', 'none' => '');+ if($mybb->input['groups'] == -1)+ {+ $group_checked['all'] = 'checked="checked"';+ }+ elseif($mybb->input['groups'] != '')+ {+ $group_checked['custom'] = 'checked="checked"';+ }+ else+ {+ $group_checked['none'] = 'checked="checked"';+ }++ print_selection_javascript();++ $groups_select_code = "+ <dl style=\"margin-top: 0; margin-bottom: 0; width: 100%\">+ <dt><label style=\"display: block;\"><input type=\"radio\" name=\"groups\" value=\"all\" {$group_checked['all']} class=\"groups_forums_groups_check\" onclick=\"checkAction('groups');\" style=\"vertical-align: middle;\" /> <strong>{$lang->all_groups}</strong></label></dt>+ <dt><label style=\"display: block;\"><input type=\"radio\" name=\"groups\" value=\"custom\" {$group_checked['custom']} class=\"groups_forums_groups_check\" onclick=\"checkAction('groups');\" style=\"vertical-align: middle;\" /> <strong>{$lang->select_groups}</strong></label></dt>+ <dd style=\"margin-top: 4px;\" id=\"groups_forums_groups_custom\" class=\"groups_forums_groups\">+ <table cellpadding=\"4\">+ <tr>+ <td valign=\"top\"><small>{$lang->groups_colon}</small></td>+ <td>".$form->generate_group_select('select[groups][]', $selected_values, array('id' => 'groups', 'multiple' => true, 'size' => 5))."</td>+ </tr>+ </table>+ </dd>+ <dt><label style=\"display: block;\"><input type=\"radio\" name=\"groups\" value=\"none\" {$group_checked['none']} class=\"groups_forums_groups_check\" onclick=\"checkAction('groups');\" style=\"vertical-align: middle;\" /> <strong>{$lang->none}</strong></label></dt>+ </dl>+ <script type=\"text/javascript\">+ checkAction('groups');+ </script>";++ $selected_values = '';+ if($mybb->input['forums'] != '' && $mybb->input['forums'] != -1)+ {+ $selected_values = explode(',', $mybb->get_input('forums'));++ foreach($selected_values as &$value)+ {+ $value = (int)$value;+ }+ unset($value);+ }++ $forum_checked = array('all' => '', 'custom' => '', 'none' => '');+ if($mybb->input['forums'] == -1)+ {+ $forum_checked['all'] = 'checked="checked"';+ }+ elseif($mybb->input['forums'] != '')+ {+ $forum_checked['custom'] = 'checked="checked"';+ }+ else+ {+ $forum_checked['none'] = 'checked="checked"';+ }++ $forums_select_code = "+ <dl style=\"margin-top: 0; margin-bottom: 0; width: 100%\">+ <dt><label style=\"display: block;\"><input type=\"radio\" name=\"forums\" value=\"all\" {$forum_checked['all']} class=\"forums_forums_groups_check\" onclick=\"checkAction('forums');\" style=\"vertical-align: middle;\" /> <strong>{$lang->all_forums}</strong></label></dt>+ <dt><label style=\"display: block;\"><input type=\"radio\" name=\"forums\" value=\"custom\" {$forum_checked['custom']} class=\"forums_forums_groups_check\" onclick=\"checkAction('forums');\" style=\"vertical-align: middle;\" /> <strong>{$lang->select_forums}</strong></label></dt>+ <dd style=\"margin-top: 4px;\" id=\"forums_forums_groups_custom\" class=\"forums_forums_groups\">+ <table cellpadding=\"4\">+ <tr>+ <td valign=\"top\"><small>{$lang->forums_colon}</small></td>+ <td>".$form->generate_forum_select('select[forums][]', $selected_values, array('id' => 'forums', 'multiple' => true, 'size' => 5))."</td>+ </tr>+ </table>+ </dd>+ <dt><label style=\"display: block;\"><input type=\"radio\" name=\"forums\" value=\"none\" {$forum_checked['none']} class=\"forums_forums_groups_check\" onclick=\"checkAction('forums');\" style=\"vertical-align: middle;\" /> <strong>{$lang->none}</strong></label></dt>+ </dl>+ <script type=\"text/javascript\">+ checkAction('forums');+ </script>";+ $form_container = new FormContainer($lang->edit_attachment_type); $form_container->output_row($lang->name, $lang->name_desc, $form->generate_text_box('name', $mybb->input['name'], array('id' => 'name')), 'name'); $form_container->output_row($lang->file_extension." <em>*</em>", $lang->file_extension_desc, $form->generate_text_box('extension', $mybb->input['extension'], array('id' => 'extension')), 'extension'); $form_container->output_row($lang->mime_type." <em>*</em>", $lang->mime_type_desc, $form->generate_text_box('mimetype', $mybb->input['mimetype'], array('id' => 'mimetype')), 'mimetype'); $form_container->output_row($lang->maximum_file_size, $lang->maximum_file_size_desc.$limit_string, $form->generate_numeric_field('maxsize', $mybb->input['maxsize'], array('id' => 'maxsize', 'min' => 0)), 'maxsize'); $form_container->output_row($lang->attachment_icon, $lang->attachment_icon_desc, $form->generate_text_box('icon', $mybb->input['icon'], array('id' => 'icon')), 'icon');+ $form_container->output_row($lang->enabled, '', $form->generate_yes_no_radio('enabled', $mybb->input['enabled']), 'enabled');+ $form_container->output_row($lang->available_to_groups, '', $groups_select_code, '', array(), array('id' => 'row_groups'));+ $form_container->output_row($lang->available_in_forums, '', $forums_select_code, '', array(), array('id' => 'row_forums'));+ $form_container->output_row($lang->avatar_file, $lang->avatar_file_desc, $form->generate_yes_no_radio('avatarfile', $mybb->input['avatarfile']), 'avatarfile'); $form_container->end(); @@ -290,6 +616,48 @@ } } +if($mybb->input['action'] == 'toggle_status')+{+ if(!verify_post_check($mybb->input['my_post_key']))+ {+ flash_message($lang->invalid_post_verify_key2, 'error');+ admin_redirect('index.php?module=config-attachment_types');+ }++ $atid = $mybb->get_input('atid', MyBB::INPUT_INT);++ $query = $db->simple_select('attachtypes', '*', "atid='{$atid}'");+ $attachment_type = $db->fetch_array($query);++ if(!$attachment_type['atid'])+ {+ flash_message($lang->error_invalid_mycode, 'error');+ admin_redirect('index.php?module=config-attachment_types');+ }++ $plugins->run_hooks('admin_config_attachment_types_toggle_status');++ $update_array = array('enabled' => 1);+ $phrase = $lang->success_activated_attachment_type;+ if($attachment_type['enabled'] == 1)+ {+ $update_array['enabled'] = 0;+ $phrase = $lang->success_activated_attachment_type;+ }++ $plugins->run_hooks('admin_config_attachment_types_toggle_status_commit');++ $db->update_query('attachtypes', $update_array, "atid='{$atid}'");++ $cache->update_attachtypes();++ // Log admin action+ log_admin_action($atid, htmlspecialchars_uni($attachment_type['extension']), $update_array['enabled']);++ flash_message($phrase, 'success');+ admin_redirect('index.php?module=config-attachment_types');+}+ if(!$mybb->input['action']) { $page->output_header($lang->attachment_types);@@ -311,15 +679,16 @@ $table = new Table; $table->construct_header($lang->extension, array("colspan" => 2)); $table->construct_header($lang->mime_type);+ $table->construct_header($lang->alt_enabled, array('class' => 'align_center')); $table->construct_header($lang->maximum_size, array("class" => "align_center"));- $table->construct_header($lang->controls, array("class" => "align_center", "colspan" => 2));+ $table->construct_header($lang->controls, array("class" => "align_center")); $query = $db->simple_select("attachtypes", "*", "", array('order_by' => 'extension')); while($attachment_type = $db->fetch_array($query)) { // Just show default icons in ACP $attachment_type['icon'] = htmlspecialchars_uni(str_replace("{theme}", "images", $attachment_type['icon']));- if(my_strpos($attachment_type['icon'], "p://") || substr($attachment_type['icon'], 0, 1) == "/")+ if(my_validate_url($attachment_type['icon'], true)) { $image = $attachment_type['icon']; }@@ -338,12 +707,29 @@ $attachment_type['icon'] = "<img src=\"{$image}\" title=\"{$attachment_type['name']}\" alt=\"\" />"; } + if($attachment_type['enabled'])+ {+ $phrase = $lang->disable;+ $icon = "on.png\" alt=\"({$lang->alt_enabled})\" title=\"{$lang->alt_enabled}";+ }+ else+ {+ $phrase = $lang->enable;+ $icon = "off.png\" alt=\"({$lang->alt_disabled})\" title=\"{$lang->alt_disabled}";+ }+ $table->construct_cell($attachment_type['icon'], array("width" => 1)); $table->construct_cell("<strong>.{$attachment_type['extension']}</strong>"); $table->construct_cell(htmlspecialchars_uni($attachment_type['mimetype']));+ $table->construct_cell("<img src=\"styles/{$page->style}/images/icons/bullet_{$icon}\" style=\"vertical-align: middle;\" />", array("class" => "align_center")); $table->construct_cell(get_friendly_size(($attachment_type['maxsize']*1024)), array("class" => "align_center"));- $table->construct_cell("<a href=\"index.php?module=config-attachment_types&action=edit&atid={$attachment_type['atid']}\">{$lang->edit}</a>", array("class" => "align_center"));- $table->construct_cell("<a href=\"index.php?module=config-attachment_types&action=delete&atid={$attachment_type['atid']}&my_post_key={$mybb->post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_attachment_type_deletion}')\">{$lang->delete}</a>", array("class" => "align_center"));++ $popup = new PopupMenu("attachment_type_{$attachment_type['atid']}", $lang->options);+ $popup->add_item($lang->edit, "index.php?module=config-attachment_types&action=edit&atid={$attachment_type['atid']}");+ $popup->add_item($phrase, "index.php?module=config-attachment_types&action=toggle_status&atid={$attachment_type['atid']}&my_post_key={$mybb->post_code}");+ $popup->add_item($lang->delete, "index.php?module=config-attachment_types&action=delete&atid={$attachment_type['atid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_attachment_type_deletion}')");+ $table->construct_cell($popup->fetch(), array('class' => 'align_center'));+ $table->construct_row(); }
# Security Analysis: MyBB Attachment Types Module
Vulnerability Existed: yes
TRUE POSITIVE
**Improper Input Validation and Sanitization - CWE-20** - CWE-20 - admin/modules/config/attachment_types.php - Lines 49-75, 340-366
**Old Code:**
```php
// No validation loop for groups/forums arrays before use
$mybb->input[$key] = implode(',', (array)$mybb->input['select'][$key]);
```
**Fixed Code:**
```php
foreach(array('groups', 'forums') as $key)
{
if($mybb->input[$key] == 'all')
{
$mybb->input[$key] = -1;
}
elseif($mybb->input[$key] == 'custom')
{
if(isset($mybb->input['select'][$key]) && is_array($mybb->input['select'][$key]))
{
foreach($mybb->input['select'][$key] as &$val)
{
$val = (int)$val; // Type casting to integer
}
unset($val);
$mybb->input[$key] = implode(',', (array)$mybb->input['select'][$key]);
}
else
{
$mybb->input[$key] = '';
}
}
else
{
$mybb->input[$key] = '';
}
}
```
**Explanation:**
The fix adds critical input validation for the groups and forums arrays before database insertion. Previously, user-supplied values from `$mybb->input['select'][$key]` could be directly imploded without type checking. The new code enforces type casting to integers `(int)$val`, preventing potential SQL injection or data corruption through malicious array values. The fix also adds proper existence checks and array validation before processing.
---
Vulnerability Existed: not sure
**Cross-Site Scripting (XSS) - CWE-79** - CWE-79 - admin/modules/config/attachment_types.php - Lines 215-290
**Old Code:**
```php
// Generated HTML with unescaped variables in onclick handlers and string concatenation
$groups_select_code = "
...
<input type=\"radio\" name=\"groups\" value=\"all\" {$group_checked['all']} class=\"groups_forums_groups_check\" onclick=\"checkAction('groups');\" ...
...";
```
**Fixed Code:**
(Same as old code - vulnerability persists)
**Explanation:**
While the fix properly type-casts array values to integers before database insertion, the HTML generation still contains potential XSS vectors. The `{$group_checked['all']}` variable is constructed from user input (`$mybb->input['groups']`) and inserted directly into HTML attributes without HTML entity encoding. If an attacker can control these checkbox states through manipulation, they could inject JavaScript. However, this may be mitigated if the MyBB framework's input handling sanitizes the values before assignment. The fix does not explicitly escape these values for HTML context, so this remains uncertain without seeing the full framework context.
--- cache/mybb_mybb_1807/admin/modules/config/languages.php 2025-12-06 11:32:55.110121074 +0000+++ cache/mybb_mybb_1808/admin/modules/config/languages.php 2025-12-06 11:32:55.906172476 +0000@@ -44,12 +44,12 @@ { $info = str_replace("\\", "\\\\", $info); $info = str_replace('$', '\$', $info);- + if($key == 'admin' || $key == 'rtl') { $info = (int)$info; }- + $newlanginfo[$key] = str_replace("\"", '\"', $info); } @@ -244,8 +244,8 @@ // Lets make nice credits header in language file $lang_file_credits = "<?php\n/**\n"; $lang_file_credits .= " * MyBB Copyright 2014 MyBB Group, All Rights Reserved\n *\n";- $lang_file_credits .= " * Website: http://www.mybb.com\n";- $lang_file_credits .= " * License: http://www.mybb.com/about/license\n *\n */\n\n";+ $lang_file_credits .= " * Website: https://mybb.com\n";+ $lang_file_credits .= " * License: https://mybb.com/about/license\n *\n */\n\n"; $lang_file_credits .= "// ".str_repeat('-',80)."\n"; $lang_file_credits .= "// MyBB Language Pack File.\n"; $lang_file_credits .= "// This file has been generated by MyBB - buildin language pack editor.\n";@@ -451,8 +451,8 @@ // Lets make nice credits header in language file $lang_file_credits = "<?php\n/**\n"; $lang_file_credits .= " * MyBB Copyright 2014 MyBB Group, All Rights Reserved\n *\n";- $lang_file_credits .= " * Website: http://www.mybb.com\n";- $lang_file_credits .= " * License: http://www.mybb.com/about/license\n *\n */\n\n";+ $lang_file_credits .= " * Website: https://mybb.com\n";+ $lang_file_credits .= " * License: https://mybb.com/about/license\n *\n */\n\n"; $lang_file_credits .= "// ".str_repeat('-',80)."\n"; $lang_file_credits .= "// MyBB Language Pack File.\n"; $lang_file_credits .= "// This file has been generated by MyBB - buildin language pack editor.\n";@@ -601,7 +601,7 @@ { $editvars[$key] = preg_replace_callback("#%u([0-9A-F]{1,4})#i", create_function('$matches', 'return "&#".hexdec($matches[1]).";";'), $editvars[$key]); }- + $form_container->output_row("", "", "", "", array('width' => '50%', 'skip_construct' => true)); $form_container->output_row($key, "", $form->generate_text_area("edit[$key]", $editvars[$key], array('id' => 'lang_'.$key, 'rows' => 2, 'class' => "langeditor_textarea_edit {$editlang_dir_class}")), 'lang_'.$key, array('width' => '50%')); }@@ -990,7 +990,7 @@ ); $sub_tabs['find_language'] = array( 'title' => $lang->find_language_packs,- 'link' => "http://community.mybb.com/mods.php?action=browse&category=19",+ 'link' => "https://community.mybb.com/mods.php?action=browse&category=19", 'target' => "_blank" );
Vulnerability Existed: no [No Security Vulnerability] - N/A - admin/modules/config/languages.php [All lines] Old Code: - `http://www.mybb.com` (lines 247, 454) - `http://www.mybb.com/about/license` (lines 248, 455) - `http://community.mybb.com/mods.php?action=browse&category=19` (line 993) Fixed Code: - `https://mybb.com` (lines 247, 454) - `https://mybb.com/about/license` (lines 248, 455) - `https://community.mybb.com/mods.php?action=browse&category=19` (line 993) Explanation: This diff contains only non-security changes: 1. **Whitespace cleanup** (lines 47, 52, 604): Trailing whitespace removed - no security impact. 2. **HTTP to HTTPS upgrade**: The changes from `http://` to `https://` in hardcoded strings represent security improvements (enforcing encrypted communication), but are not fixing existing vulnerabilities in the code itself. These are static strings used in generated language pack file headers and link targets, not affecting input validation, authentication, or data handling. 3. **Domain simplification** (`www.mybb.com` → `mybb.com`): URL shortening in static strings - no security impact. These are best-practice improvements and maintenance changes, not vulnerability fixes.
--- cache/mybb_mybb_1807/admin/modules/config/module_meta.php 2025-12-06 11:32:55.114121333 +0000+++ cache/mybb_mybb_1808/admin/modules/config/module_meta.php 2025-12-06 11:32:55.906172476 +0000@@ -39,6 +39,7 @@ $sub_menu['150'] = array("id" => "warning", "title" => $lang->warning_system, "link" => "index.php?module=config-warning"); $sub_menu['160'] = array("id" => "thread_prefixes", "title" => $lang->thread_prefixes, "link" => "index.php?module=config-thread_prefixes"); $sub_menu['170'] = array("id" => "questions", "title" => $lang->security_questions, "link" => "index.php?module=config-questions");+ $sub_menu['180'] = array("id" => "report_reasons", "title" => $lang->report_reasons, "link" => "index.php?module=config-report_reasons"); $sub_menu = $plugins->run_hooks("admin_config_menu", $sub_menu); @@ -75,7 +76,8 @@ 'mycode' => array('active' => 'mycode', 'file' => 'mycode.php'), 'settings' => array('active' => 'settings', 'file' => 'settings.php'), 'thread_prefixes' => array('active' => 'thread_prefixes', 'file' => 'thread_prefixes.php'),- 'questions' => array('active' => 'questions', 'file' => 'questions.php')+ 'questions' => array('active' => 'questions', 'file' => 'questions.php'),+ 'report_reasons' => array('active' => 'report_reasons', 'file' => 'report_reasons.php') ); $actions = $plugins->run_hooks("admin_config_action_handler", $actions);@@ -116,7 +118,8 @@ "warning" => $lang->can_manage_warning_system, "mod_tools" => $lang->can_manage_mod_tools, "thread_prefixes" => $lang->can_manage_thread_prefixes,- "questions" => $lang->can_manage_security_questions+ "questions" => $lang->can_manage_security_questions,+ "report_reasons" => $lang->can_manage_report_reasons ); $admin_permissions = $plugins->run_hooks("admin_config_permissions", $admin_permissions);
Vulnerability Existed: no
No Vulnerabilities Detected - [N/A] - admin/modules/config/module_meta.php [All lines]
Old Code:
```php
$sub_menu['170'] = array("id" => "questions", "title" => $lang->security_questions, "link" => "index.php?module=config-questions");
'questions' => array('active' => 'questions', 'file' => 'questions.php')
"questions" => $lang->can_manage_security_questions
```
Fixed Code:
```php
$sub_menu['170'] = array("id" => "questions", "title" => $lang->security_questions, "link" => "index.php?module=config-questions");
$sub_menu['180'] = array("id" => "report_reasons", "title" => $lang->report_reasons, "link" => "index.php?module=config-report_reasons");
'questions' => array('active' => 'questions', 'file' => 'questions.php'),
'report_reasons' => array('active' => 'report_reasons', 'file' => 'report_reasons.php')
"questions" => $lang->can_manage_security_questions,
"report_reasons" => $lang->can_manage_report_reasons
```
Explanation:
This diff adds a new menu item and corresponding action handler configuration for a "report_reasons" admin module. The changes are purely structural additions that extend the admin configuration menu system. There are no security vulnerabilities in this code:
1. **No User Input Handling**: The additions are static array definitions with hardcoded strings and language variable references
2. **No SQL Injection Risk**: No database queries are constructed with user input
3. **No XSS Risk**: All values use language variables (`$lang->report_reasons`, `$lang->can_manage_report_reasons`) which should be pre-escaped by the framework
4. **No Authentication Bypass**: The module follows existing permission patterns (`can_manage_report_reasons`)
5. **No Path Traversal**: The file reference `report_reasons.php` is a static filename in a controlled directory
This is a legitimate feature addition following the established MyBB module registration pattern.
--- cache/mybb_mybb_1807/admin/modules/config/plugins.php 2025-12-06 11:32:55.114121333 +0000+++ cache/mybb_mybb_1808/admin/modules/config/plugins.php 2025-12-06 11:32:55.906172476 +0000@@ -67,7 +67,7 @@ // Convert to mods site version codes $search_version = ($major_version_code/100).'x'; - $contents = fetch_remote_file("http://community.mybb.com/xmlbrowse.php?type=plugins&version={$search_version}{$keywords}{$url_page}", $post_data);+ $contents = fetch_remote_file("https://community.mybb.com/xmlbrowse.php?type=plugins&version={$search_version}{$keywords}{$url_page}", $post_data); if(!$contents) {@@ -116,7 +116,7 @@ $table->construct_cell("<strong>{$result['name']['value']}</strong><br /><small>{$result['description']['value']}</small><br /><i><small>{$lang->created_by} {$result['author']['value']}</small></i>"); $table->construct_cell($result['version']['value'], array("class" => "align_center"));- $table->construct_cell("<strong><a href=\"http://community.mybb.com/{$result['download_url']['value']}\" target=\"_blank\">{$lang->download}</a></strong>", array("class" => "align_center"));+ $table->construct_cell("<strong><a href=\"https://community.mybb.com/{$result['download_url']['value']}\" target=\"_blank\">{$lang->download}</a></strong>", array("class" => "align_center")); $table->construct_row(); } }@@ -186,11 +186,11 @@ // Recommended plugins = Default; Otherwise search results & pagination if($mybb->request_method == "post") {- $table->output("<span style=\"float: right;\"><small><a href=\"http://community.mybb.com/mods.php?action=browse&category=plugins\" target=\"_blank\">{$lang->browse_all_plugins}</a></small></span>".$lang->sprintf($lang->browse_results_for_mybb, $mybb->version));+ $table->output("<span style=\"float: right;\"><small><a href=\"https://community.mybb.com/mods.php?action=browse&category=plugins\" target=\"_blank\">{$lang->browse_all_plugins}</a></small></span>".$lang->sprintf($lang->browse_results_for_mybb, $mybb->version)); } else {- $table->output("<span style=\"float: right;\"><small><a href=\"http://community.mybb.com/mods.php?action=browse&category=plugins\" target=\"_blank\">{$lang->browse_all_plugins}</a></small></span>".$lang->sprintf($lang->recommended_plugins_for_mybb, $mybb->version));+ $table->output("<span style=\"float: right;\"><small><a href=\"https://community.mybb.com/mods.php?action=browse&category=plugins\" target=\"_blank\">{$lang->browse_all_plugins}</a></small></span>".$lang->sprintf($lang->recommended_plugins_for_mybb, $mybb->version)); } echo "<br />".draw_admin_pagination($mybb->input['page'], 15, $tree['results']['attributes']['total'], "index.php?module=config-plugins&action=browse{$keywords}&page={page}");@@ -242,7 +242,7 @@ admin_redirect("index.php?module=config-plugins"); } - $url = "http://community.mybb.com/version_check.php?";+ $url = "https://community.mybb.com/version_check.php?"; $url .= http_build_query(array("info" => $info))."&"; require_once MYBB_ROOT."inc/class_xml.php"; $contents = fetch_remote_file($url);@@ -328,7 +328,7 @@ } else {- $table->construct_cell("<strong><a href=\"http://community.mybb.com/{$plugin['download_url']['value']}\" target=\"_blank\">{$lang->download}</a></strong>", array("class" => "align_center"));+ $table->construct_cell("<strong><a href=\"https://community.mybb.com/{$plugin['download_url']['value']}\" target=\"_blank\">{$lang->download}</a></strong>", array("class" => "align_center")); } $table->construct_row(); }
Vulnerability Existed: no
[Insecure Transport - CWE-319] - CWE-319 - admin/modules/config/plugins.php [Lines 70, 119, 189, 192, 245, 331]
[Old Code]
http://community.mybb.com/xmlbrowse.php?type=plugins&version={$search_version}{$keywords}{$url_page}
http://community.mybb.com/{$result['download_url']['value']}
http://community.mybb.com/mods.php?action=browse&category=plugins
http://community.mybb.com/version_check.php?
[Fixed Code]
https://community.mybb.com/xmlbrowse.php?type=plugins&version={$search_version}{$keywords}{$url_page}
https://community.mybb.com/{$result['download_url']['value']}
https://community.mybb.com/mods.php?action=browse&category=plugins
https://community.mybb.com/version_check.php?
Explanation:
These changes upgrade all HTTP URLs to HTTPS for communication with community.mybb.com. This fixes a vulnerability where unencrypted HTTP connections could expose sensitive data in transit to man-in-the-middle attacks. The vulnerability existed in the old code because:
1. Remote file fetches (`fetch_remote_file()`) over HTTP transmitted data without encryption
2. Plugin download links and browsing URLs sent over HTTP could be intercepted
3. Version check requests over HTTP could allow tampering with version information
The fix eliminates the insecure transport vulnerability by enforcing HTTPS encryption for all remote communications with the MyBB community site.
--- cache/mybb_mybb_1807/admin/modules/config/post_icons.php 2025-12-06 11:32:55.114121333 +0000+++ cache/mybb_mybb_1808/admin/modules/config/post_icons.php 2025-12-06 11:32:55.910172735 +0000@@ -465,7 +465,7 @@ while($icon = $db->fetch_array($query)) { $icon['path'] = str_replace("{theme}", "images", $icon['path']);- if(my_strpos($icon['path'], "p://") || substr($icon['path'], 0, 1) == "/")+ if(my_validate_url($icon['path'], true)) { $image = $icon['path']; }
Vulnerability Existed: yes TRUE POSITIVE CWE-22 (Improper Limitation of a Pathname to a Restricted Directory) - CWE-22 - admin/modules/config/post_icons.php Line 468 Old Code: ```php if(my_strpos($icon['path'], "p://") || substr($icon['path'], 0, 1) == "/") ``` Fixed Code: ```php if(my_validate_url($icon['path'], true)) ``` Explanation: The original code attempted to validate whether a path was either an absolute URL (containing "p://") or an absolute filesystem path (starting with "/"). However, this validation was flawed: 1. **Incomplete protocol check**: `my_strpos($icon['path'], "p://")` only checks for the substring "p://", which would match "http://", "https://", "ftp://", etc., but this is an imprecise way to validate URLs. 2. **Path traversal vulnerability**: The check `substr($icon['path'], 0, 1) == "/"` allows any absolute filesystem path, including paths with directory traversal sequences like `/../` that could escape intended restrictions. 3. **Missing validation of relative paths**: Relative paths without these markers weren't validated, allowing potentially malicious relative paths to be used. The fix uses `my_validate_url($icon['path'], true)`, which is a proper validation function that should comprehensively check whether the path is a valid URL or safe absolute path, preventing path traversal attacks and ensuring only intended paths are used for loading post icons.
--- /dev/null+++ cache/mybb_mybb_1808/admin/modules/config/report_reasons.php@@ -0,0 +1,449 @@+<?php+/**+ * MyBB 1.8+ * Copyright 2014 MyBB Group, All Rights Reserved+ *+ * Website: http://www.mybb.com+ * License: http://www.mybb.com/about/license+ *+ */++// Disallow direct access to this file for security reasons+if(!defined("IN_MYBB"))+{+ die("Direct initialization of this file is not allowed.<br /><br />Please make sure IN_MYBB is defined.");+}++$page->add_breadcrumb_item($lang->report_reasons, "index.php?module=config-report_reasons");++$content_types = array('post', 'profile', 'reputation');++$content_types = $plugins->run_hooks("report_content_types", $content_types);++$plugins->run_hooks("admin_config_report_reasons_begin");++if($mybb->input['action'] == "add")+{+ cast_content_inputs();++ $plugins->run_hooks("admin_config_report_reasons_add");++ if($mybb->request_method == "post")+ {+ if(!trim($mybb->input['title']))+ {+ $errors[] = $lang->error_missing_title;+ }++ if($mybb->input['extra'] != 0 && $mybb->input['extra'] != 1)+ {+ $errors[] = $lang->error_missing_extra;+ }++ if(!$errors)+ {+ if($mybb->input['appliesto'] != 'all')+ {+ $appliesto = array();+ asort($content_types);+ foreach($content_types as $content)+ {+ if($mybb->input["appliesto_{$content}"] == 1)+ {+ $appliesto[] = $content;+ }+ }+ $appliesto = implode(",", $appliesto);+ }+ else+ {+ $appliesto = 'all';+ }++ $new_reason = array(+ "title" => $db->escape_string($mybb->input['title']),+ "appliesto" => $db->escape_string($appliesto),+ "extra" => $mybb->input['extra']+ );+ $rid = $db->insert_query("reportreasons", $new_reason);++ $plugins->run_hooks("admin_config_report_reasons_add_commit");++ $cache->update_reportreasons();++ // Log admin action+ log_admin_action($rid, $mybb->input['title']);++ flash_message($lang->success_reason_created, 'success');+ admin_redirect("index.php?module=config-report_reasons");+ }+ }++ $page->add_breadcrumb_item($lang->add_new_reason);+ $page->output_header($lang->report_reasons." - ".$lang->add_new_reason);++ $sub_tabs['report_reasons'] = array(+ 'title' => $lang->report_reasons,+ 'link' => "index.php?module=config-report_reasons"+ );++ $sub_tabs['add_new_reason'] = array(+ 'title' => $lang->add_new_reason,+ 'link' => "index.php?module=config-report_reasons&action=add",+ 'description' => $lang->add_new_reason_desc+ );++ $page->output_nav_tabs($sub_tabs, 'add_new_reason');++ $form = new Form("index.php?module=config-report_reasons&action=add", "post", "add");++ if($errors)+ {+ $page->output_inline_error($errors);+ }+ else+ {+ $mybb->input['extra'] = 0;+ }++ $form_container = new FormContainer($lang->add_new_reason);+ $form_container->output_row($lang->reason_title." <em>*</em>", $lang->reason_title_desc, $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title');+ $form_container->output_row($lang->applies_to." <em>*</em>", $lang->applies_to_desc, generate_content_select());+ $form_container->output_row($lang->requires_extra." <em>*</em>", $lang->requires_extra_desc, $form->generate_yes_no_radio('extra', $mybb->input['extra']));+ $form_container->end();++ $buttons[] = $form->generate_submit_button($lang->save_reason);++ $form->output_submit_wrapper($buttons);+ $form->end();++ $page->output_footer();+}++if($mybb->input['action'] == "edit")+{+ $query = $db->simple_select("reportreasons", "*", "rid='".$mybb->get_input('rid', MyBB::INPUT_INT)."'");+ $reason = $db->fetch_array($query);++ if(!$reason['rid'])+ {+ flash_message($lang->error_invalid_reason, 'error');+ admin_redirect("index.php?module=config-report_reasons");+ }+ elseif($reason['rid'] == 1)+ {+ flash_message($lang->error_cannot_modify_reason, 'error');+ admin_redirect("index.php?module=config-report_reasons");+ }++ cast_content_inputs();++ $plugins->run_hooks("admin_config_report_reasons_edit");++ if($mybb->request_method == "post")+ {+ if(!trim($mybb->input['title']))+ {+ $errors[] = $lang->error_missing_title;+ }++ if($mybb->input['extra'] != 0 && $mybb->input['extra'] != 1)+ {+ $errors[] = $lang->error_missing_extra;+ }++ if(!$errors)+ {+ if($mybb->input['appliesto'] != 'all')+ {+ $appliesto = array();+ asort($content_types);+ foreach($content_types as $content)+ {+ if($mybb->input["appliesto_{$content}"] == 1)+ {+ $appliesto[] = $content;+ }+ }+ $appliesto = implode(",", $appliesto);+ }+ else+ {+ $appliesto = 'all';+ }++ $updated_reason = array(+ "title" => $db->escape_string($mybb->input['title']),+ "appliesto" => $db->escape_string($appliesto),+ "extra" => $mybb->input['extra']+ );++ $plugins->run_hooks("admin_config_report_reasons_edit_commit");++ $db->update_query("reportreasons", $updated_reason, "rid='{$reason['rid']}'");++ $cache->update_reportreasons();++ // Log admin action+ log_admin_action($reason['rid'], $mybb->input['title']);++ flash_message($lang->success_reason_updated, 'success');+ admin_redirect("index.php?module=config-report_reasons");+ }+ }++ $page->add_breadcrumb_item($lang->edit_reason);+ $page->output_header($lang->report_reasons." - ".$lang->edit_reason);++ $sub_tabs['edit_reason'] = array(+ 'title' => $lang->edit_reason,+ 'link' => "index.php?module=config-report_reasons&action=edit&rid={$reason['rid']}",+ 'description' => $lang->edit_reason_desc+ );++ $page->output_nav_tabs($sub_tabs, 'edit_reason');++ $form = new Form("index.php?module=config-report_reasons&action=edit&rid={$reason['rid']}", "post", "add");++ if($errors)+ {+ $page->output_inline_error($errors);+ }+ else+ {+ $mybb->input = $reason;+ $appliesto = explode(",", $reason['appliesto']);+ foreach($appliesto as $content)+ {+ $mybb->input["appliesto_{$content}"] = 1;+ }+ }++ $form_container = new FormContainer($lang->add_new_reason);+ $form_container->output_row($lang->reason_title." <em>*</em>", $lang->reason_title_desc, $form->generate_text_box('title', $mybb->input['title'], array('id' => 'title')), 'title');+ $form_container->output_row($lang->applies_to." <em>*</em>", $lang->applies_to_desc, generate_content_select());+ $form_container->output_row($lang->requires_extra." <em>*</em>", $lang->requires_extra_desc, $form->generate_yes_no_radio('extra', $mybb->input['extra']));+ $form_container->end();++ $buttons[] = $form->generate_submit_button($lang->save_reason);++ $form->output_submit_wrapper($buttons);+ $form->end();++ $page->output_footer();+}++if($mybb->input['action'] == "delete")+{+ if($mybb->input['no'])+ {+ admin_redirect("index.php?module=config-report_reasons");+ }++ $query = $db->simple_select("reportreasons", "*", "rid='".$mybb->get_input('rid', MyBB::INPUT_INT)."'");+ $reason = $db->fetch_array($query);++ if(!$reason['rid'])+ {+ flash_message($lang->error_invalid_reason, 'error');+ admin_redirect("index.php?module=config-report_reasons");+ }+ elseif($reason['rid'] == 1)+ {+ flash_message($lang->error_cannot_delete_reason, 'error');+ admin_redirect("index.php?module=config-report_reasons");+ }++ $plugins->run_hooks("admin_config_report_reasons_delete");++ if($mybb->request_method == "post")+ {++ // Change the reason of associated reports to Other and carry over the title+ $updated_report = array(+ 'reasonid' => 1,+ 'reason' => $db->escape_string($reason['title'])+ );+ $db->update_query("reports", $updated_report, "reasonid='{$reason['rid']}'");++ $db->delete_query("reportreasons", "rid='{$reason['rid']}'");++ $plugins->run_hooks("admin_config_report_reasons_delete_commit");++ // Log admin action+ log_admin_action($reason['rid'], $reason['title']);++ flash_message($lang->success_reason_deleted, 'success');+ admin_redirect("index.php?module=config-report_reasons");+ }+ else+ {+ $page->output_confirm_action("index.php?module=config-report_reasons&action=delete&qid={$question['qid']}", $lang->confirm_reason_deletion);+ }+}++if(!$mybb->input['action'])+{+ $plugins->run_hooks("admin_config_report_reasons_start");++ if($mybb->request_method == "post")+ {+ if(!empty($mybb->input['disporder']))+ {+ foreach($mybb->input['disporder'] as $rid => $order)+ {+ $db->update_query("reportreasons", array('disporder' => (int)$order), "rid='".(int)$rid."'");+ }++ $plugins->run_hooks("admin_config_report_reasons_start_commit");++ //$cache->update_reportreasons();++ flash_message($lang->success_reasons_disporder_updated, 'success');+ admin_redirect("index.php?module=config-report_reasons");+ }+ }++ $page->output_header($lang->report_reasons);++ $sub_tabs['report_reasons'] = array(+ 'title' => $lang->report_reasons,+ 'link' => "index.php?module=config-report_reasons",+ 'description' => $lang->report_reasons_desc+ );+ $sub_tabs['add_new_reason'] = array(+ 'title' => $lang->add_new_reason,+ 'link' => "index.php?module=config-report_reasons&action=add",+ );++ $page->output_nav_tabs($sub_tabs, 'report_reasons');++ $form = new Form("index.php?module=config-report_reasons", "post", "reasons");++ $form_container = new FormContainer($lang->report_reasons);+ $form_container->output_row_header($lang->reason_title);+ $form_container->output_row_header($lang->applies_to, array("width" => "35%"));+ $form_container->output_row_header($lang->extra_comment, array("width" => "10%", "class" => "align_center"));+ $form_container->output_row_header($lang->order, array("width" => "5%", "class" => "align_center"));+ $form_container->output_row_header($lang->controls, array("class" => "align_center", "width" => 150));++ $query = $db->simple_select("reportreasons", "*", "", array('order_by' => 'disporder'));+ while($reasons = $db->fetch_array($query))+ {+ $reasons['title'] = $lang->parse($reasons['title']);++ $reasons['appliesto'] = explode(",", $reasons['appliesto']);++ $appliesto = array();+ foreach($reasons['appliesto'] as $content)+ {+ $key = "report_content_".$content;+ $appliesto[] = $lang->$key;+ }+ $reasons['appliesto'] = implode(", ", $appliesto);++ if($reasons['extra'] == 1)+ {+ $icon = "<img src=\"styles/{$page->style}/images/icons/bullet_on.png\" alt=\"({$lang->yes})\" title=\"{$lang->yes}\" style=\"vertical-align: middle;\" /> ";+ }+ else+ {+ $icon = "<img src=\"styles/{$page->style}/images/icons/bullet_off.png\" alt=\"({$lang->no})\" title=\"{$lang->no}\" style=\"vertical-align: middle;\" /> ";+ }++ $form_container->output_cell(htmlspecialchars_uni($reasons['title']));+ $form_container->output_cell(htmlspecialchars_uni($reasons['appliesto']));+ $form_container->output_cell("<div>{$icon}</div>", array("class" => "align_center"));+ $form_container->output_cell("<input type=\"text\" name=\"disporder[{$reasons['rid']}]\" value=\"{$reasons['disporder']}\" class=\"text_input align_center\" style=\"width: 80%;\" />", array("class" => "align_center"));+ $popup = new PopupMenu("reasons_{$reasons['rid']}", $lang->options);+ $popup->add_item($lang->edit_reason, "index.php?module=config-report_reasons&action=edit&rid={$reasons['rid']}");+ $popup->add_item($lang->delete_reason, "index.php?module=config-report_reasons&action=delete&rid={$reasons['rid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->confirm_reason_deletion}')");+ $form_container->output_cell($popup->fetch(), array("class" => "align_center"));+ $form_container->construct_row();+ }++ if($form_container->num_rows() == 0)+ {+ $form_container->construct_cell($lang->no_report_reasons, array('colspan' => 5));+ $form_container->construct_row();+ }++ $form_container->end();++ $buttons = array();+ $buttons[] = $form->generate_submit_button($lang->update_reasons_order);+ $form->output_submit_wrapper($buttons);++ $form->end();++ $page->output_footer();+}++function generate_content_select()+{+ global $mybb, $lang;++ $checked = array('all' => '', 'custom' => '', 'none' => '');+ if($mybb->input['appliesto'] == 'all')+ {+ $checked['all'] = 'checked="checked"';+ }+ elseif($mybb->input['appliesto'] == '')+ {+ $checked['none'] = 'checked="checked"';+ }+ else+ {+ $checked['custom'] = 'checked="checked"';+ }++ print_selection_javascript();++ return "<dl style=\"margin-top: 0; margin-bottom: 0; width: 100%\">+ <dt><label style=\"display: block;\"><input type=\"radio\" name=\"appliesto\" value=\"all\" {$checked['all']} class=\"appliesto_forums_groups_check\" onclick=\"checkAction('appliesto');\" style=\"vertical-align: middle;\" /> <strong>{$lang->all_content}</strong></label></dt>+ <dt><label style=\"display: block;\"><input type=\"radio\" name=\"appliesto\" value=\"custom\" {$checked['custom']} class=\"appliesto_forums_groups_check\" onclick=\"checkAction('appliesto');\" style=\"vertical-align: middle;\" /> <strong>{$lang->select_content}</strong></label></dt>+ <dd style=\"margin-top: 4px;\" id=\"appliesto_forums_groups_custom\" class=\"appliesto_forums_groups\">+ <table cellpadding=\"4\">+ <tr>+ <td valign=\"top\"><small>{$lang->content_colon}</small></td>+ <td>".implode("<br />", generate_content_choices())."</td>+ </tr>+ </table>+ </dd>+ <dt><label style=\"display: block;\"><input type=\"radio\" name=\"appliesto\" value=\"none\" {$checked['none']} class=\"appliesto_forums_groups_check\" onclick=\"checkAction('appliesto');\" style=\"vertical-align: middle;\" /> <strong>{$lang->none}</strong></label></dt>+ </dl>+ <script type=\"text/javascript\">+ checkAction('appliesto');+ </script>";+}++function generate_content_choices()+{+ global $mybb, $lang, $form, $content_types;++ asort($content_types);++ $content_choices = array();+ foreach($content_types as $content)+ {+ $key = "report_content_{$content}";+ $content_choices[] = $form->generate_check_box("appliesto_{$content}", 1, $lang->$key, array('id' => "appliesto_{$content}", 'checked' => $mybb->input["appliesto_{$content}"]));+ }++ return $content_choices;+}++function cast_content_inputs()+{+ global $mybb, $content_types;++ asort($content_types);++ foreach($content_types as $content)+ {+ $key = "appliesto_{$content}";+ $mybb->input[$key] = $mybb->get_input($key, MyBB::INPUT_INT);+ }++ $mybb->input['extra'] = $mybb->get_input('extra', MyBB::INPUT_INT);+}
Vulnerability Existed: not sure
SQL Injection - CWE-89 - admin/modules/config/report_reasons.php - Lines 207, 257
Old Code:
```php
$db->update_query("reportreasons", $updated_reason, "rid='{$reason['rid']}'");
```
Fixed Code:
```php
$db->update_query("reportreasons", $updated_reason, "rid='{$reason['rid']}'");
```
Explanation:
This is a newly added file (created from /dev/null), so there is no "old code" to compare against. The code uses `$reason['rid']` which was retrieved via `$mybb->get_input('rid', MyBB::INPUT_INT)` at line 118, which properly casts the input to an integer. While the rid value is inserted directly into the SQL query string at lines 207 and 257, the `MyBB::INPUT_INT` cast at retrieval time provides type safety. However, the pattern of string interpolation in SQL queries (even with cast inputs) is not ideal practice. The code does not appear to be a "fix" since it's a new file, so there's uncertainty whether this represents a vulnerability fix or simply the baseline code.
---
Vulnerability Existed: not sure
Potential XSS - CWE-79 - admin/modules/config/report_reasons.php - Lines 347-349
Old Code:
```php
[New file - no old code]
```
Fixed Code:
```php
$form_container->output_cell("<div>{$icon}</div>", array("class" => "align_center"));
$form_container->output_cell("<input type=\"text\" name=\"disporder[{$reasons['rid']}]\" value=\"{$reasons['disporder']}\" class=\"text_input align_center\" style=\"width: 80%;\" />", array("class" => "align_center"));
$popup = new PopupMenu("reasons_{$reasons['rid']}", $lang->options);
```
Explanation:
The code directly interpolates `$reasons['rid']` and `$reasons['disporder']` into HTML attributes without explicit escaping at lines 347-349. While `$reasons['rid']` is an integer from the database and should be safe, `$reasons['disporder']` is retrieved from user input via `$mybb->input['disporder']` at line 293 and cast to `(int)`. The code does use `htmlspecialchars_uni()` for the title and appliesto fields at lines 342-343, showing awareness of escaping needs. However, since this is a new file with no prior version to compare, it's uncertain whether this represents a security fix or simply the baseline code. The integer casting provides some protection, but the inconsistent escaping pattern is noteworthy.
--- cache/mybb_mybb_1807/admin/modules/config/settings.php 2025-12-06 11:32:55.118121590 +0000+++ cache/mybb_mybb_1808/admin/modules/config/settings.php 2025-12-06 11:32:55.910172735 +0000@@ -882,60 +882,72 @@ admin_redirect("index.php?module=config-settings"); } - // If we are changing the hidden captcha, make sure it doesn't conflict with another registration field- if(isset($mybb->input['upsetting']['hiddencaptchaimagefield']))- {- // Not allowed to be hidden captcha fields- $disallowed_fields = array(- 'username',- 'password',- 'password2',- 'email',- 'email2',- 'imagestring',- 'imagehash',- 'answer',- 'question_id',- 'allownotices',- 'hideemail',- 'receivepms',- 'pmnotice',- 'emailpmnotify',- 'invisible',- 'subscriptionmethod',- 'timezoneoffset',- 'dstcorrection',- 'language',- 'step',- 'action',- 'agree',- 'regtime',- 'regcheck1',- 'regcheck2',- 'regsubmit'- );+ // Not allowed to be hidden captcha fields+ $disallowed_fields = array(+ 'username',+ 'password',+ 'password2',+ 'email',+ 'email2',+ 'imagestring',+ 'imagehash',+ 'answer',+ 'question_id',+ 'allownotices',+ 'hideemail',+ 'receivepms',+ 'pmnotice',+ 'emailpmnotify',+ 'invisible',+ 'subscriptionmethod',+ 'timezoneoffset',+ 'dstcorrection',+ 'language',+ 'step',+ 'action',+ 'agree',+ 'regtime',+ 'regcheck1',+ 'regcheck2',+ 'regsubmit'+ ); - if(in_array($mybb->input['upsetting']['hiddencaptchaimagefield'], $disallowed_fields))+ $is_current_hiddencaptcha_wrong = in_array($mybb->settings['hiddencaptchaimagefield'], $disallowed_fields);+ if(in_array($mybb->input['upsetting']['hiddencaptchaimagefield'], $disallowed_fields) || $is_current_hiddencaptcha_wrong)+ {+ if(isset($mybb->input['upsetting']['hiddencaptchaimagefield']) && $mybb->input['upsetting']['hiddencaptchaimagefield'] != $mybb->settings['hiddencaptchaimagefield'] && !$is_current_hiddencaptcha_wrong) {- // Whoopsies, you can't do that!- $error_message = $lang->sprintf($lang->error_hidden_captcha_conflict, htmlspecialchars_uni($mybb->input['upsetting']['hiddencaptchaimagefield']));-- flash_message($error_message, 'error');- admin_redirect("index.php?module=config-settings&action=change&gid=9");+ $wrong_value = $mybb->input['upsetting']['hiddencaptchaimagefield'];+ $mybb->input['upsetting']['hiddencaptchaimagefield'] = $mybb->settings['hiddencaptchaimagefield'];+ }+ else+ {+ $wrong_value = $mybb->settings['hiddencaptchaimagefield'];+ $mybb->input['upsetting']['hiddencaptchaimagefield'] = 'email3'; }++ $lang->success_settings_updated .= $lang->sprintf($lang->success_settings_updated_hiddencaptchaimage, htmlspecialchars_uni($mybb->input['upsetting']['hiddencaptchaimagefield']), htmlspecialchars_uni($wrong_value));+ }++ // Have we opted for a reCAPTCHA and not set a public/private key?+ if((isset($mybb->input['upsetting']['captchaimage']) && in_array($mybb->input['upsetting']['captchaimage'], array(2, 4)) && (!$mybb->input['upsetting']['captchaprivatekey'] || !$mybb->input['upsetting']['captchapublickey']))+ || (in_array($mybb->settings['captchaimage'], array(2, 4)) && (!$mybb->settings['captchaprivatekey'] || !$mybb->settings['captchapublickey'])))+ {+ $mybb->input['upsetting']['captchaimage'] = 1;+ $lang->success_settings_updated .= $lang->success_settings_updated_captchaimage; } // Get settings which optionscode is a forum/group select, checkbox or numeric // We cannot rely on user input to decide this $checkbox_settings = $forum_group_select = array(); $query = $db->simple_select('settings', 'name, optionscode', "optionscode IN('forumselect', 'groupselect', 'numeric') OR optionscode LIKE 'checkbox%'");- + while($multisetting = $db->fetch_array($query)) { if(substr($multisetting['optionscode'], 0, 8) == 'checkbox') { $checkbox_settings[] = $multisetting['name'];- + // All checkboxes deselected = no $mybb->input['upsetting'] for them, we need to initialize it manually then, but only on pages where the setting is shown if(empty($mybb->input['upsetting'][$multisetting['name']]) && isset($mybb->input["isvisible_{$multisetting['name']}"])) {@@ -955,6 +967,22 @@ } } + // Administrator is changing the login method.+ if($mybb->settings['username_method'] == 1 || $mybb->settings['username_method'] == 2 || $mybb->input['upsetting']['username_method'] == 1 || $mybb->input['upsetting']['username_method'] == 2)+ {+ $query = $db->simple_select('users', 'email, COUNT(email) AS duplicates', "email!=''", array('group_by' => 'email HAVING duplicates>1'));+ if($db->num_rows($query))+ {+ $mybb->input['upsetting']['username_method'] = 0;+ $lang->success_settings_updated .= $lang->success_settings_updated_username_method;+ }+ else+ {+ $mybb->input['upsetting']['allowmultipleemails'] = 0;+ $lang->success_settings_updated .= $lang->success_settings_updated_allowmultipleemails;+ }+ }+ if(is_array($mybb->input['upsetting'])) { foreach($mybb->input['upsetting'] as $name => $value)@@ -990,13 +1018,13 @@ elseif($checkbox_settings && in_array($name, $checkbox_settings)) { $value = '';- + if(is_array($mybb->input['upsetting'][$name])) { $value = implode(',', $mybb->input['upsetting'][$name]); } }- + $db->update_query("settings", array('value' => $db->escape_string($value)), "name='".$db->escape_string($name)."'"); } }@@ -1017,45 +1045,32 @@ // If the delayedthreadviews setting was changed, enable or disable the tasks for it. if(isset($mybb->input['upsetting']['delayedthreadviews']) && $mybb->settings['delayedthreadviews'] != $mybb->input['upsetting']['delayedthreadviews']) {- if($mybb->input['upsetting']['delayedthreadviews'] == 0)- {- $updated_task = array(- "enabled" => 0- );- }- else- {- $updated_task = array(- "enabled" => 1- );- }- $db->update_query("tasks", $updated_task, "file='threadviews'");+ $db->update_query("tasks", array('enabled' => (int)$mybb->input['upsetting']['delayedthreadviews']), "file='threadviews'"); } // Have we changed our cookie prefix? If so, update our adminsid so we're not logged out- if($mybb->input['upsetting']['cookieprefix'] && $mybb->input['upsetting']['cookieprefix'] != $mybb->settings['cookieprefix'])+ if(isset($mybb->input['upsetting']['cookieprefix']) && $mybb->input['upsetting']['cookieprefix'] != $mybb->settings['cookieprefix']) { my_unsetcookie("adminsid"); $mybb->settings['cookieprefix'] = $mybb->input['upsetting']['cookieprefix']; my_setcookie("adminsid", $admin_session['sid'], '', true); } - // Have we opted for a reCAPTCHA and not set a public/private key?- if($mybb->input['upsetting']['captchaimage'] == 2 && !$mybb->input['upsetting']['captchaprivatekey'] && !$mybb->input['upsetting']['captchapublickey'])+ if(isset($mybb->input['upsetting']['statstopreferrer']) && $mybb->input['upsetting']['statstopreferrer'] != $mybb->settings['statstopreferrer'])+ {+ $cache->update_statistics();+ }++ if(isset($mybb->input['upsetting']['statslimit']) && $mybb->input['upsetting']['statslimit'] != $mybb->settings['statstopreferrer']) {- $db->update_query("settings", array("value" => 1), "name = 'captchaimage'");+ $cache->update_most_replied_threads();+ $cache->update_most_viewed_threads(); } rebuild_settings(); $plugins->run_hooks("admin_config_settings_change_commit"); - // If we have changed our report reasons recache them- if(isset($mybb->input['upsetting']['reportreasons']))- {- $cache->update_reportedposts();- }- // Log admin action log_admin_action(); @@ -1380,12 +1395,12 @@ else { $typecount = count($type);- + if($type[0] == 'checkbox') { $multivalue = explode(',', $setting['value']); }- + for($i = 0; $i < $typecount; $i++) { $optionsexp = explode("=", $type[$i]);@@ -1426,7 +1441,7 @@ } } }- + if($type[0] == "select") { $setting_code = $form->generate_select_box($element_name, $option_list, $setting['value'], array('id' => $element_id));@@ -1434,7 +1449,7 @@ else { $setting_code = implode("<br />", $option_list);- + if($type[0] == 'checkbox') { $setting_code .= $form->generate_hidden_field("isvisible_{$setting['name']}", 1);@@ -1442,7 +1457,7 @@ } $option_list = array(); }- + // Do we have a custom language variable for this title or description? $title_lang = "setting_".$setting['name']; $desc_lang = $title_lang."_desc";@@ -1639,7 +1654,7 @@ echo '</div>'; echo '-<script type="text/javascript" src="./jscripts/search.js"></script>+<script type="text/javascript" src="./jscripts/search.js?ver=1808"></script> <script type="text/javascript"> //<!-- $(document).ready(function(){
```
Vulnerability Existed: yes
FALSE POSITIVE
SQL Injection - CWE-89 - admin/modules/config/settings.php Lines 973
Old Code:
$query = $db->simple_select('users', 'email, COUNT(email) AS duplicates', "email!=''", array('group_by' => 'email HAVING duplicates>1'));
Fixed Code:
(No fix present in diff - vulnerability introduced)
Explanation:
The code uses `simple_select()` with a GROUP_BY clause containing user-controlled input through the array parameter. The `email HAVING duplicates>1` portion is passed in the options array without proper escaping. While this appears to be a static string in this context, the pattern is vulnerable if the HAVING clause were ever constructed from user input. However, examining this specific case, it appears to be a logic issue rather than a direct SQL injection - the HAVING clause syntax may be incorrectly passed to the database abstraction layer depending on how `simple_select()` handles the options array.
```
```
Vulnerability Existed: not sure
Type Juggling / Logic Error - CWE-1025 - admin/modules/config/settings.php Line 1048
Old Code:
$db->update_query("tasks", $updated_task, "file='threadviews'");
(where $updated_task conditionally set to array with "enabled" => 0 or 1)
Fixed Code:
$db->update_query("tasks", array('enabled' => (int)$mybb->input['upsetting']['delayedthreadviews']), "file='threadviews'");
Explanation:
The fix explicitly casts the value to `(int)`, which is a security improvement. The old code relied on PHP's type juggling where 0 or 1 from user input could be interpreted as boolean true/false. By explicitly casting to integer, it prevents potential type confusion vulnerabilities. However, this is more of a defensive coding practice than a critical security fix, as the value is ultimately stored in a database and used for comparison.
```
```
Vulnerability Existed: no
Information Disclosure Prevention - CWE-200 - admin/modules/config/settings.php Line 934
Old Code:
if(in_array($mybb->input['upsetting']['hiddencaptchaimagefield'], $disallowed_fields))
{
$error_message = $lang->sprintf($lang->error_hidden_captcha_conflict, htmlspecialchars_uni($mybb->input['upsetting']['hiddencaptchaimagefield']));
flash_message($error_message, 'error');
admin_redirect("index.php?module=config-settings&action=change&gid=9");
}
Fixed Code:
(Removes early rejection and silently resets to safe defaults with success message)
Explanation:
The old code explicitly returned an error when an invalid hidden captcha field was selected, which could leak information about the validation logic. The fix silently resets to safe defaults and shows a success message instead, preventing information disclosure about what values are not allowed.
```
--- cache/mybb_mybb_1807/admin/modules/config/smilies.php 2025-12-06 11:32:55.118121590 +0000+++ cache/mybb_mybb_1808/admin/modules/config/smilies.php 2025-12-06 11:32:55.910172735 +0000@@ -643,7 +643,7 @@ while($smilie = $db->fetch_array($query)) { $smilie['image'] = str_replace("{theme}", "images", $smilie['image']);- if(my_strpos($smilie['image'], "p://") || substr($smilie['image'], 0, 1) == "/")+ if(my_validate_url($smilie['image'], true)) { $image = $smilie['image']; }@@ -726,10 +726,9 @@ while($smilie = $db->fetch_array($query)) { $smilie['image'] = str_replace("{theme}", "images", $smilie['image']);- if(my_strpos($smilie['image'], "p://") || substr($smilie['image'], 0, 1) == "/")+ if(my_validate_url($smilie['image'], true)) { $image = $smilie['image'];- $smilie['image'] = str_replace("{theme}", "images", $smilie['image']); } else {
Vulnerability Existed: yes
TRUE POSITIVE
[URL Validation Bypass - CWE-601 (URL Redirection to Untrusted Site)] - CWE-601 - admin/modules/config/smilies.php [Lines 646 & 729]
Old Code:
```php
if(my_strpos($smilie['image'], "p://") || substr($smilie['image'], 0, 1) == "/")
{
$image = $smilie['image'];
}
```
Fixed Code:
```php
if(my_validate_url($smilie['image'], true))
{
$image = $smilie['image'];
}
```
Explanation:
The original code attempted to validate URLs by checking if the string contained "p://" (matching "http://" or "https://") or started with "/". This is an insufficient URL validation approach that could be bypassed:
- The check for "p://" is incomplete and fragile (only checking for the end of the protocol)
- It doesn't validate the actual URL structure or scheme properly
- It could allow malicious URLs like "javascript://", "data://", or other protocol-based attacks
- It doesn't prevent URL redirection attacks or other URL-based vulnerabilities
The fix replaces this with `my_validate_url($smilie['image'], true)`, which uses a proper URL validation function. The `true` parameter likely indicates strict validation mode, ensuring that only legitimate URLs (http/https or local paths) are accepted, preventing URL-based attacks.
Additionally, line 733 removes a redundant `str_replace()` call that was unnecessarily duplicating the image path transformation, which also improves code correctness.
--- cache/mybb_mybb_1807/admin/modules/forum/announcements.php 2025-12-06 11:32:55.118121590 +0000+++ cache/mybb_mybb_1808/admin/modules/forum/announcements.php 2025-12-06 11:32:55.910172735 +0000@@ -230,14 +230,12 @@ if(!$mybb->input['starttime_time']) {- $start_time = explode("-", gmdate("g-i-a", TIME_NOW));- $mybb->input['starttime_time'] = $start_time[0].":".$start_time[1]." ".$start_time[2];+ $mybb->input['starttime_time'] = gmdate($mybb->settings['timeformat'], TIME_NOW); } if(!$mybb->input['endtime_time']) {- $end_time = explode("-", gmdate("g-i-a", TIME_NOW));- $mybb->input['endtime_time'] = $end_time[0].":".$end_time[1]." ".$end_time[2];+ $mybb->input['endtime_time'] = gmdate($mybb->settings['timeformat'], TIME_NOW); } if($mybb->input['starttime_day'])@@ -619,8 +617,7 @@ admin_redirect("index.php?module=forum-announcements"); } - $start_time = explode("-", gmdate("g-i-a", $announcement['startdate']));- $mybb->input['starttime_time'] = $start_time[0].":".$start_time[1]." ".$start_time[2];+ $mybb->input['starttime_time'] = gmdate( $mybb->settings['timeformat'], $announcement['startdate']); $startday = gmdate("j", $announcement['startdate']); @@ -641,8 +638,7 @@ $endtime_checked[1] = "checked=\"checked\""; $endtime_checked[2] = ""; - $end_time = explode("-", gmdate("g-i-a", $announcement['enddate']));- $mybb->input['endtime_time'] = $end_time[0].":".$end_time[1]." ".$end_time[2];+ $mybb->input['endtime_time'] = gmdate( $mybb->settings['timeformat'],$announcement['enddate']); $endday = gmdate("j", $announcement['enddate']);
Vulnerability Existed: no
No Vulnerabilities Detected - Code Quality and Logic Improvement Only
Explanation:
This diff represents a refactoring improvement rather than a security fix. The changes replace manual string parsing logic with direct use of PHP's `gmdate()` function with a configurable time format setting.
**Analysis of the change:**
Old Code:
```php
$start_time = explode("-", gmdate("g-i-a", TIME_NOW));
$mybb->input['starttime_time'] = $start_time[0].":".$start_time[1]." ".$start_time[2];
```
Fixed Code:
```php
$mybb->input['starttime_time'] = gmdate($mybb->settings['timeformat'], TIME_NOW);
```
**Why this is not a security vulnerability fix:**
1. **No injection vulnerability existed**: The old code did not contain SQL injection, command injection, or any exploitable vulnerability. The string concatenation was safe because it was operating on the output of `gmdate()`, not user input.
2. **No XSS or encoding issues**: The time formatting was not being directly output to HTML without escaping, so there was no XSS vector present.
3. **Nature of the change**: This is a code quality improvement that:
- Simplifies logic by removing unnecessary `explode()` operations
- Respects user-configured time formats from settings rather than hard-coding "g-i-a"
- Reduces code duplication (same pattern repeated 4 times in the diff)
- Improves maintainability
4. **Security neutral**: The refactoring maintains the same data flow and does not introduce or remove any security boundaries.
**Conclusion**: This diff represents good software engineering practice—simplifying code and respecting configuration settings—but it is not addressing a security vulnerability.
--- cache/mybb_mybb_1807/admin/modules/forum/attachments.php 2025-12-06 11:32:55.122121849 +0000+++ cache/mybb_mybb_1808/admin/modules/forum/attachments.php 2025-12-06 11:32:55.910172735 +0000@@ -187,17 +187,17 @@ { case "pgsql": $query = $db->query("- SELECT a.*, u.uid AS useruid, u.username, SUM(a.filesize) as totalsize+ SELECT a.uid, u.username, SUM(a.filesize) as totalsize FROM ".TABLE_PREFIX."attachments a LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=a.uid)- GROUP BY ".$db->build_fields_string("attachments", "a.").",u.uid,u.username+ GROUP BY a.uid, u.username ORDER BY totalsize DESC LIMIT 5 "); break; default: $query = $db->query("- SELECT a.*, u.uid AS useruid, u.username, SUM(a.filesize) as totalsize+ SELECT a.uid, u.username, SUM(a.filesize) as totalsize FROM ".TABLE_PREFIX."attachments a LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=a.uid) GROUP BY a.uid@@ -207,11 +207,11 @@ } while($user = $db->fetch_array($query)) {- if(!$user['useruid'])+ if(!$user['uid']) { $user['username'] = $lang->na; }- $table->construct_cell(build_profile_link($user['username'], $user['useruid'], "_blank"));+ $table->construct_cell(build_profile_link(htmlspecialchars_uni($user['username']), $user['uid'], "_blank")); $table->construct_cell("<a href=\"index.php?module=forum-attachments&results=1&username=".urlencode($user['username'])."\" target=\"_blank\">".get_friendly_size($user['totalsize'])."</a>", array('class' => 'align_center')); $table->construct_row(); }@@ -848,7 +848,7 @@ $form_container->output_row($lang->name_contains, $lang->name_contains_desc, $form->generate_text_box('filename', $mybb->input['filename'], array('id' => 'filename')), 'filename'); $form_container->output_row($lang->type_contains, "", $form->generate_text_box('mimetype', $mybb->input['mimetype'], array('id' => 'mimetype')), 'mimetype'); $form_container->output_row($lang->forum_is, "", $form->generate_forum_select('forum[]', $mybb->input['forum'], array('multiple' => true, 'size' => 5, 'id' => 'forum')), 'forum');- $form_container->output_row($lang->username_is, "", $form->generate_text_box('username', $mybb->input['username'], array('id' => 'username')), 'username');+ $form_container->output_row($lang->username_is, "", $form->generate_text_box('username', htmlspecialchars_uni($mybb->get_input('username')), array('id' => 'username')), 'username'); $more_options = array( "less_than" => $lang->more_than,@@ -945,9 +945,9 @@ if($attachment['user_username']) {- $attachment['username'] = $attachment['username'];+ $attachment['username'] = $attachment['user_username']; }- $table->construct_cell(build_profile_link($attachment['username'], $attachment['uid'], "_blank"), array("class" => "align_center"));+ $table->construct_cell(build_profile_link(htmlspecialchars_uni($attachment['username']), $attachment['uid'], "_blank"), array("class" => "align_center")); $table->construct_cell("<a href=\"../".get_post_link($attachment['pid'])."\" target=\"_blank\">".htmlspecialchars_uni($attachment['subject'])."</a>", array("class" => "align_center")); $table->construct_cell(my_number_format($attachment['downloads']), array("class" => "align_center")); if($attachment['dateuploaded'] > 0)
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - admin/modules/forum/attachments.php [214]
Old Code:
```php
$table->construct_cell(build_profile_link($user['username'], $user['useruid'], "_blank"));
```
Fixed Code:
```php
$table->construct_cell(build_profile_link(htmlspecialchars_uni($user['username']), $user['uid'], "_blank"));
```
Explanation:
The username was being passed directly to `build_profile_link()` without proper HTML escaping. If a username contained HTML/JavaScript characters, they could be rendered in the page, enabling Stored XSS. The fix applies `htmlspecialchars_uni()` to escape the username before passing it to the function.
---
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - admin/modules/forum/attachments.php [851]
Old Code:
```php
$form_container->output_row($lang->username_is, "", $form->generate_text_box('username', $mybb->input['username'], array('id' => 'username')), 'username');
```
Fixed Code:
```php
$form_container->output_row($lang->username_is, "", $form->generate_text_box('username', htmlspecialchars_uni($mybb->get_input('username')), array('id' => 'username')), 'username');
```
Explanation:
User input from `$mybb->input['username']` was being rendered in a form field without escaping. The fix uses `htmlspecialchars_uni()` to properly escape the value and also changes to `$mybb->get_input()` (which may provide additional sanitization). This prevents XSS when the username parameter is reflected in the form.
---
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - admin/modules/forum/attachments.php [951]
Old Code:
```php
$table->construct_cell(build_profile_link($attachment['username'], $attachment['uid'], "_blank"), array("class" => "align_center"));
```
Fixed Code:
```php
$table->construct_cell(build_profile_link(htmlspecialchars_uni($attachment['username']), $attachment['uid'], "_blank"), array("class" => "align_center"));
```
Explanation:
Similar to the first vulnerability, the attachment username was passed to `build_profile_link()` without HTML escaping. The fix applies `htmlspecialchars_uni()` to prevent XSS if the username contains malicious characters.
---
Vulnerability Existed: not sure
Data Integrity Issue - N/A - admin/modules/forum/attachments.php [948]
Old Code:
```php
$attachment['username'] = $attachment['username'];
```
Fixed Code:
```php
$attachment['username'] = $attachment['user_username'];
```
Explanation:
This appears to be a logic bug rather than a security vulnerability. The original code was self-assigning `$attachment['username']` to itself, which suggests the developer intended to use `$attachment['user_username']` instead. The fix assigns the correct field. While not a direct security vulnerability, this could lead to incorrect data being displayed (data integrity issue) if the intended field is actually from the joined users table.
--- cache/mybb_mybb_1807/admin/modules/forum/management.php 2025-12-06 11:32:55.122121849 +0000+++ cache/mybb_mybb_1808/admin/modules/forum/management.php 2025-12-06 11:32:55.910172735 +0000@@ -2582,7 +2582,7 @@ echo $form->generate_hidden_field("fid", $mybb->input['fid']); echo $form->generate_hidden_field("add", "moderators"); $form_container = new FormContainer($lang->add_user_as_moderator);- $form_container->output_row($lang->username." <em>*</em>", $lang->moderator_username_desc, $form->generate_text_box('username', $mybb->input['username'], array('id' => 'username')), 'username');+ $form_container->output_row($lang->username." <em>*</em>", $lang->moderator_username_desc, $form->generate_text_box('username', htmlspecialchars_uni($mybb->get_input('username')), array('id' => 'username')), 'username'); $form_container->end(); // Autocompletion for usernames
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - admin/modules/forum/management.php - Line 2585
Old Code:
```php
$form->generate_text_box('username', $mybb->input['username'], array('id' => 'username'))
```
Fixed Code:
```php
$form->generate_text_box('username', htmlspecialchars_uni($mybb->get_input('username')), array('id' => 'username'))
```
Explanation:
The original code directly passed unsanitized user input (`$mybb->input['username']`) to the form text box without HTML encoding. This creates a reflected XSS vulnerability where an attacker could inject malicious JavaScript through the `username` parameter. The fixed version applies `htmlspecialchars_uni()` to encode HTML special characters, preventing the injected code from being executed. Additionally, the fix uses `$mybb->get_input('username')` which is the recommended input retrieval method (likely with built-in validation/sanitization) instead of direct array access. This is a proper XSS mitigation for output in an HTML context.
--- cache/mybb_mybb_1807/admin/modules/forum/moderation_queue.php 2025-12-06 11:32:55.122121849 +0000+++ cache/mybb_mybb_1808/admin/modules/forum/moderation_queue.php 2025-12-06 11:32:55.914172993 +0000@@ -229,7 +229,7 @@ } else {- $profile_link = build_profile_link($thread['username'], $thread['uid'], "_blank");+ $profile_link = build_profile_link(htmlspecialchars_uni($thread['username']), $thread['uid'], "_blank"); } $thread['postmessage'] = nl2br(htmlspecialchars_uni($thread['postmessage']));@@ -374,7 +374,7 @@ } else {- $profile_link = build_profile_link($post['username'], $post['uid'], "_blank");+ $profile_link = build_profile_link(htmlspecialchars_uni($post['username']), $post['uid'], "_blank"); } $post['message'] = nl2br(htmlspecialchars_uni($post['message']));@@ -510,7 +510,7 @@ $link = get_post_link($attachment['pid'], $attachment['tid']) . "#pid{$attachment['pid']}"; $thread_link = get_thread_link($attachment['tid']);- $profile_link = build_profile_link($attachment['username'], $attachment['uid'], "_blank");+ $profile_link = build_profile_link(htmlspecialchars_uni($attachment['username']), $attachment['uid'], "_blank"); $table->construct_cell("<a href=\"../attachment.php?aid={$attachment['aid']}\" target=\"_blank\">{$attachment['filename']}</a> ({$attachment['filesize']})<br /><small class=\"modqueue_meta\">{$lang->post} <a href=\"{$link}\" target=\"_blank\">{$attachment['postsubject']}</a></small>"); $table->construct_cell($profile_link, array("class" => "align_center"));
Based on the diff provided, here is my security analysis: --- ## Vulnerability Analysis **Vulnerability 1:** Vulnerability Existed: yes TRUE POSITIVE Cross-Site Scripting (XSS) - CWE-79 - admin/modules/forum/moderation_queue.php - Lines 232, 377, 513 **Old Code:** ```php $profile_link = build_profile_link($thread['username'], $thread['uid'], "_blank"); $profile_link = build_profile_link($post['username'], $post['uid'], "_blank"); $profile_link = build_profile_link($attachment['username'], $attachment['uid'], "_blank"); ``` **Fixed Code:** ```php $profile_link = build_profile_link(htmlspecialchars_uni($thread['username']), $thread['uid'], "_blank"); $profile_link = build_profile_link(htmlspecialchars_uni($post['username']), $post['uid'], "_blank"); $profile_link = build_profile_link(htmlspecialchars_uni($attachment['username']), $attachment['uid'], "_blank"); ``` **Explanation:** The vulnerability existed because usernames were passed directly to `build_profile_link()` without HTML encoding. If a username contains special HTML characters or malicious JavaScript payloads (e.g., `<img src=x onerror="alert(1)">`), these would be rendered directly in the HTML output without sanitization. By wrapping the username parameters with `htmlspecialchars_uni()`, the fix properly escapes HTML special characters, preventing XSS attacks. The `htmlspecialchars_uni()` function converts characters like `<`, `>`, `&`, and quotes to their HTML entity equivalents, ensuring user-controlled input cannot be interpreted as executable code or HTML tags. This fix is applied consistently across all three vulnerable code locations in the moderation queue module.
--- cache/mybb_mybb_1807/admin/modules/home/credits.php 2025-12-06 11:32:55.122121849 +0000+++ cache/mybb_mybb_1808/admin/modules/home/credits.php 2025-12-06 11:32:55.914172993 +0000@@ -30,7 +30,7 @@ $sub_tabs['credits_about'] = array( 'title' => $lang->about_the_team,- 'link' => "http://www.mybb.com/about/team",+ 'link' => "https://mybb.com/about/team", 'link_target' => "_blank", ); @@ -52,7 +52,7 @@ ); require_once MYBB_ROOT."inc/class_xml.php";- $contents = fetch_remote_file("http://www.mybb.com/mybb_team.xml");+ $contents = fetch_remote_file("https://mybb.com/mybb_team.xml"); if(!$contents) {@@ -149,4 +149,3 @@ $page->output_footer(); }-
Vulnerability Existed: no
HTTPS Upgrade - No CWE - admin/modules/home/credits.php Lines 33, 55
Old Code:
```
'link' => "http://www.mybb.com/about/team",
$contents = fetch_remote_file("http://www.mybb.com/mybb_team.xml");
```
Fixed Code:
```
'link' => "https://mybb.com/about/team",
$contents = fetch_remote_file("https://mybb.com/mybb_team.xml");
```
Explanation:
This change upgrades two HTTP URLs to HTTPS and removes the "www" subdomain. While HTTP transmission could theoretically be vulnerable to man-in-the-middle attacks, this is not a code vulnerability per se—it's a protocol/configuration change. The code itself had no vulnerability; the change improves security posture by using encrypted transport. Additionally, a trailing newline removal at line 152 is a formatting change with no security impact.
--- cache/mybb_mybb_1807/admin/modules/home/index.php 2025-12-06 11:32:55.122121849 +0000+++ cache/mybb_mybb_1808/admin/modules/home/index.php 2025-12-06 11:32:55.914172993 +0000@@ -39,7 +39,7 @@ ); require_once MYBB_ROOT."inc/class_xml.php";- $contents = fetch_remote_file("http://www.mybb.com/version_check.php");+ $contents = fetch_remote_file("https://mybb.com/version_check.php"); if(!$contents) {@@ -264,9 +264,13 @@ $query = $db->simple_select("reportedcontent", "COUNT(*) AS reported_posts", "type = 'post' OR type = ''"); $reported_posts = my_number_format($db->fetch_field($query, "reported_posts")); - // Get the number of reported posts that haven't been marked as read yet- $query = $db->simple_select("reportedcontent", "COUNT(*) AS new_reported_posts", "reportstatus='0' AND (type = 'post' OR type = '')");- $new_reported_posts = my_number_format($db->fetch_field($query, "new_reported_posts"));+ // If report medium is MCP...+ if($mybb->settings['reportmethod'] == "db")+ {+ // Get the number of reported posts that haven't been marked as read yet+ $query = $db->simple_select("reportedcontent", "COUNT(*) AS new_reported_posts", "reportstatus='0' AND (type = 'post' OR type = '')");+ $new_reported_posts = my_number_format($db->fetch_field($query, "new_reported_posts"));+ } // Get the number and total file size of attachments $query = $db->simple_select("attachments", "COUNT(*) AS numattachs, SUM(filesize) as spaceused", "visible='1' AND pid > '0'");@@ -291,7 +295,7 @@ // If the update check contains information about a newer version, show an alert if(isset($update_check['latest_version_code']) && $update_check['latest_version_code'] > $mybb->version_code) {- $lang->new_version_available = $lang->sprintf($lang->new_version_available, "MyBB {$mybb->version}", "<a href=\"http://www.mybb.com/downloads\" target=\"_blank\">MyBB {$update_check['latest_version']}</a>");+ $lang->new_version_available = $lang->sprintf($lang->new_version_available, "MyBB {$mybb->version}", "<a href=\"https://mybb.com/downloads\" target=\"_blank\">MyBB {$update_check['latest_version']}</a>"); $page->output_error("<p><em>{$lang->new_version_available}</em></p>"); } @@ -312,7 +316,14 @@ $table->construct_cell("<strong>{$lang->php_version}</strong>", array('width' => '25%')); $table->construct_cell(PHP_VERSION, array('width' => '25%')); $table->construct_cell("<strong>{$lang->posts}</strong>", array('width' => '25%'));- $table->construct_cell("<strong>{$posts}</strong> {$lang->posts}<br /><strong>{$newposts}</strong> {$lang->new_today}<br /><a href=\"index.php?module=forum-moderation_queue&type=posts\"><strong>{$unapproved_posts}</strong> {$lang->unapproved}</a><br /><strong>{$reported_posts}</strong> {$lang->reported_posts}<br /><strong>{$new_reported_posts}</strong> {$lang->unread_reports}", array('width' => '25%'));+ if($mybb->settings['reportmethod'] == "db")+ {+ $table->construct_cell("<strong>{$posts}</strong> {$lang->posts}<br /><strong>{$newposts}</strong> {$lang->new_today}<br /><a href=\"index.php?module=forum-moderation_queue&type=posts\"><strong>{$unapproved_posts}</strong> {$lang->unapproved}</a><br /><strong>{$reported_posts}</strong> {$lang->reported_posts}<br /><strong>{$new_reported_posts}</strong> {$lang->unread_reports}", array('width' => '25%'));+ }+ else+ {+ $table->construct_cell("<strong>{$posts}</strong> {$lang->posts}<br /><strong>{$newposts}</strong> {$lang->new_today}<br /><a href=\"index.php?module=forum-moderation_queue&type=posts\"><strong>{$unapproved_posts}</strong> {$lang->unapproved}</a><br /><strong>{$reported_posts}</strong> {$lang->reported_posts}", array('width' => '25%'));+ } $table->construct_row(); $table->construct_cell("<strong>{$lang->sql_engine}</strong>", array('width' => '25%'));
Vulnerability Existed: yes
TRUE POSITIVE
Man-in-the-Middle (MitM) Attack via Insecure HTTP - CWE-295 - admin/modules/home/index.php lines 42, 294
Old Code:
```
$contents = fetch_remote_file("http://www.mybb.com/version_check.php");
```
and
```
$lang->new_version_available = $lang->sprintf($lang->new_version_available, "MyBB {$mybb->version}", "<a href=\"http://www.mybb.com/downloads\" target=\"_blank\">MyBB {$update_check['latest_version']}</a>");
```
Fixed Code:
```
$contents = fetch_remote_file("https://mybb.com/version_check.php");
```
and
```
$lang->new_version_available = $lang->sprintf($lang->new_version_available, "MyBB {$mybb->version}", "<a href=\"https://mybb.com/downloads\" target=\"_blank\">MyBB {$update_check['latest_version']}</a>");
```
Explanation:
The original code used HTTP (unencrypted) connections to fetch version information and link to downloads from mybb.com. This is vulnerable to man-in-the-middle attacks where an attacker could intercept the connection and serve malicious version check responses or redirect users to compromised download pages. The fix upgrades both connections to HTTPS, providing encryption and authentication to prevent MitM attacks. Additionally, the domain was changed from "www.mybb.com" to "mybb.com", which may also represent a legitimate site migration.
---
Vulnerability Existed: not sure
Uninitialized Variable - CWE-457 - admin/modules/home/index.php lines 268-275
Old Code:
```
// Get the number of reported posts that haven't been marked as read yet
$query = $db->simple_select("reportedcontent", "COUNT(*) AS new_reported_posts", "reportstatus='0' AND (type = 'post' OR type = '')");
$new_reported_posts = my_number_format($db->fetch_field($query, "new_reported_posts"));
```
Fixed Code:
```
// If report medium is MCP...
if($mybb->settings['reportmethod'] == "db")
{
// Get the number of reported posts that haven't been marked as read yet
$query = $db->simple_select("reportedcontent", "COUNT(*) AS new_reported_posts", "reportstatus='0' AND (type = 'post' OR type = '')");
$new_reported_posts = my_number_format($db->fetch_field($query, "new_reported_posts"));
}
```
Explanation:
The fix conditionally initializes `$new_reported_posts` only when `$mybb->settings['reportmethod'] == "db"`. However, the variable is still used later at line 324 without guarantee of initialization if the condition is false. This could cause an undefined variable notice/warning. The fix appears incomplete—`$new_reported_posts` should be initialized to a default value (e.g., empty string or "0") before the conditional, or the usage at line 324 should also be wrapped in the same condition (which it is, based on the diff). Assuming the conditional wrapper at line 319-325 properly guards all usage, this may not be a vulnerability, but it's uncertain without seeing the complete context.
---
Vulnerability Existed: not sure
Logic Error / Incomplete Refactoring - CWE-697 - admin/modules/home/index.php lines 319-325
Old Code:
```
$table->construct_cell("<strong>{$posts}</strong> {$lang->posts}<br /><strong>{$newposts}</strong> {$lang->new_today}<br /><a href=\"index.php?module=forum-moderation_queue&type=posts\"><strong>{$unapproved_posts}</strong> {$lang->unapproved}</a><br /><strong>{$reported_posts}</strong> {$lang->reported_posts}<br /><strong>{$new_reported_posts}</strong> {$lang->unread_reports}", array('width' => '25%'));
```
Fixed Code:
```
if($mybb->settings['reportmethod'] == "db")
{
$table->construct_cell("<strong>{$posts}</strong> {$lang->posts}<br /><strong>{$newposts}</strong> {$lang->new_today}<br /><a href=\"index.php?module=forum-moderation_queue&type=posts\"><strong>{$unapproved_posts}</strong> {$lang->unapproved}</a><br /><strong>{$reported_posts}</strong> {$lang->reported_posts}<br /><strong>{$new_reported_posts}</strong> {$lang->unread_reports}", array('width' => '25%'));
}
else
{
$table->construct_cell("<strong>{$posts}</strong> {$lang->posts}<br /><strong>{$newposts}</strong> {$lang->new_today}<br /><a href=\"index.php?module=forum-moderation_queue&type=posts\"><strong>{$unapproved_posts}</strong> {$lang->unapproved}</a><br /><strong>{$reported_posts}</strong> {$lang->reported_posts}", array('width' => '25%'));
}
```
Explanation:
The fix adds a conditional check that displays different content based on the report method. When the method is not "db", the unread reports line is omitted. This appears to be an intentional feature change rather than a vulnerability fix—it prevents displaying `$new_reported_posts` (which would be undefined) when the report method is not "db". However, without understanding the business logic of what "reportmethod" values are valid and how they affect report handling, it's uncertain whether this conditional logic correctly handles all cases or if there are missing scenarios.
--- cache/mybb_mybb_1807/admin/modules/home/module_meta.php 2025-12-06 11:32:55.122121849 +0000+++ cache/mybb_mybb_1808/admin/modules/home/module_meta.php 2025-12-06 11:32:55.914172993 +0000@@ -24,7 +24,7 @@ $sub_menu = array(); $sub_menu['10'] = array("id" => "dashboard", "title" => $lang->dashboard, "link" => "index.php?module=home-dashboard"); $sub_menu['20'] = array("id" => "preferences", "title" => $lang->preferences, "link" => "index.php?module=home-preferences");- $sub_menu['30'] = array("id" => "docs", "title" => $lang->mybb_documentation, "link" => "http://docs.mybb.com");+ $sub_menu['30'] = array("id" => "docs", "title" => $lang->mybb_documentation, "link" => "https://docs.mybb.com"); $sub_menu['40'] = array("id" => "credits", "title" => $lang->mybb_credits, "link" => "index.php?module=home-credits"); $sub_menu = $plugins->run_hooks("admin_home_menu", $sub_menu); @@ -166,7 +166,7 @@ $class = ""; } $ip_address = my_inet_ntop($db->unescape_binary($user['ip']));- $online_users .= "<li title=\"{$lang->ipaddress} {$ip_address}\"{$class}>".build_profile_link($user['username'].' ('.$ip_address.')', $user['uid'], "_blank")."</li>";+ $online_users .= "<li title=\"{$lang->ipaddress} {$ip_address}\"{$class}>".build_profile_link(htmlspecialchars_uni($user['username']).' ('.$ip_address.')', $user['uid'], "_blank")."</li>"; $done_users["{$user['uid']}.{$user['ip']}"] = 1; } }
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - admin/modules/home/module_meta.php Line 169
Old Code:
```php
$online_users .= "<li title=\"{$lang->ipaddress} {$ip_address}\"{$class}>".build_profile_link($user['username'].' ('.$ip_address.')', $user['uid'], "_blank")."</li>";
```
Fixed Code:
```php
$online_users .= "<li title=\"{$lang->ipaddress} {$ip_address}\"{$class}>".build_profile_link(htmlspecialchars_uni($user['username']).' ('.$ip_address.')', $user['uid'], "_blank")."</li>";
```
Explanation:
The vulnerability existed because `$user['username']` was being directly concatenated into HTML output without escaping. An attacker could register a username containing malicious JavaScript (e.g., `<img src=x onerror=alert('xss')>`) and when the admin viewed the online users list, the script would execute in their browser. The fix applies `htmlspecialchars_uni()` to escape the username, converting special HTML characters to entities so they render as text rather than executable code. Note: `$ip_address` appears to already be safely processed through `my_inet_ntop()` which handles binary IP data, so it's less of a concern, but the username was the primary injection vector here.
---
Vulnerability Existed: no
Unencrypted Connection - CWE-295 - admin/modules/home/module_meta.php Line 27
Old Code:
```php
$sub_menu['30'] = array("id" => "docs", "title" => $lang->mybb_documentation, "link" => "http://docs.mybb.com");
```
Fixed Code:
```php
$sub_menu['30'] = array("id" => "docs", "title" => $lang->mybb_documentation, "link" => "https://docs.mybb.com");
```
Explanation:
While this is a security improvement, it's not fixing a vulnerability that existed in the traditional sense—it's a hardening measure. The old link used unencrypted HTTP, which could theoretically expose the connection to man-in-the-middle attacks. Changing to HTTPS (secure) is a best practice, but the vulnerability would only manifest if an attacker actively intercepted the connection. The fix ensures documentation links use encrypted HTTPS connections, protecting against passive eavesdropping and active interception attacks.
--- cache/mybb_mybb_1807/admin/modules/style/templates.php 2025-12-06 11:32:55.122121849 +0000+++ cache/mybb_mybb_1808/admin/modules/style/templates.php 2025-12-06 11:32:55.914172993 +0000@@ -264,7 +264,7 @@ <link href="./jscripts/codemirror/addon/dialog/dialog-mybb.css" rel="stylesheet"> <script src="./jscripts/codemirror/addon/dialog/dialog.js"></script> <script src="./jscripts/codemirror/addon/search/searchcursor.js"></script>-<script src="./jscripts/codemirror/addon/search/search.js"></script>+<script src="./jscripts/codemirror/addon/search/search.js?ver=1808"></script> <script src="./jscripts/codemirror/addon/fold/foldcode.js"></script> <script src="./jscripts/codemirror/addon/fold/xml-fold.js"></script> <script src="./jscripts/codemirror/addon/fold/foldgutter.js"></script>@@ -636,7 +636,7 @@ <link href="./jscripts/codemirror/addon/dialog/dialog-mybb.css" rel="stylesheet"> <script src="./jscripts/codemirror/addon/dialog/dialog.js"></script> <script src="./jscripts/codemirror/addon/search/searchcursor.js"></script>-<script src="./jscripts/codemirror/addon/search/search.js"></script>+<script src="./jscripts/codemirror/addon/search/search.js?ver=1808"></script> <script src="./jscripts/codemirror/addon/fold/foldcode.js"></script> <script src="./jscripts/codemirror/addon/fold/xml-fold.js"></script> <script src="./jscripts/codemirror/addon/fold/foldgutter.js"></script>@@ -1176,7 +1176,7 @@ <link href="./jscripts/codemirror/addon/dialog/dialog-mybb.css" rel="stylesheet"> <script src="./jscripts/codemirror/addon/dialog/dialog.js"></script> <script src="./jscripts/codemirror/addon/search/searchcursor.js"></script>-<script src="./jscripts/codemirror/addon/search/search.js"></script>+<script src="./jscripts/codemirror/addon/search/search.js?ver=1808"></script> <script src="./jscripts/codemirror/addon/fold/foldcode.js"></script> <script src="./jscripts/codemirror/addon/fold/xml-fold.js"></script> <script src="./jscripts/codemirror/addon/fold/foldgutter.js"></script>
Vulnerability Existed: no No Vulnerability - Cache Busting Parameter - File admin/modules/style/templates.php [Lines 267, 639, 1179] Old Code: ``` <script src="./jscripts/codemirror/addon/search/search.js"></script> ``` Fixed Code: ``` <script src="./jscripts/codemirror/addon/search/search.js?ver=1808"></script> ``` Explanation: This change adds a cache-busting query parameter (`?ver=1808`) to a script source URL. This is a **security hardening measure**, not a vulnerability fix. The parameter ensures browsers fetch the latest version of the script file rather than serving a cached version that may contain vulnerabilities or bugs from a previous release. Cache busting is a legitimate technique to force clients to download updated resources after version updates. By appending a version number that changes between releases, the browser's cache key differs, preventing stale code from being used. This is particularly important for security patches where outdated cached JavaScript could expose users to vulnerabilities that have been fixed in newer versions. This change improves security posture by ensuring script updates are not bypassed due to browser caching.
--- cache/mybb_mybb_1807/admin/modules/style/themes.php 2025-12-06 11:32:55.122121849 +0000+++ cache/mybb_mybb_1808/admin/modules/style/themes.php 2025-12-06 11:32:55.914172993 +0000@@ -168,7 +168,7 @@ // Convert to mods site version codes $search_version = ($major_version_code/100).'x'; - $contents = fetch_remote_file("http://community.mybb.com/xmlbrowse.php?type=themes&version={$search_version}{$keywords}{$url_page}", $post_data);+ $contents = fetch_remote_file("https://community.mybb.com/xmlbrowse.php?type=themes&version={$search_version}{$keywords}{$url_page}", $post_data); if(!$contents) {@@ -214,9 +214,9 @@ ); $result['download_url']['value'] = htmlspecialchars_uni(html_entity_decode($result['download_url']['value'])); - $table->construct_cell("<img src=\"http://community.mybb.com/{$result['thumbnail']['value']}\" alt=\"{$lang->theme_thumbnail}\" title=\"{$lang->theme_thumbnail}\"/>", array("class" => "align_center", "width" => 100));+ $table->construct_cell("<img src=\"https://community.mybb.com/{$result['thumbnail']['value']}\" alt=\"{$lang->theme_thumbnail}\" title=\"{$lang->theme_thumbnail}\"/>", array("class" => "align_center", "width" => 100)); $table->construct_cell("<strong>{$result['name']['value']}</strong><br /><small>{$result['description']['value']}</small><br /><i><small>{$lang->created_by} {$result['author']['value']}</small></i>");- $table->construct_cell("<strong><a href=\"http://community.mybb.com/{$result['download_url']['value']}\" target=\"_blank\">{$lang->download}</a></strong>", array("class" => "align_center"));+ $table->construct_cell("<strong><a href=\"https://community.mybb.com/{$result['download_url']['value']}\" target=\"_blank\">{$lang->download}</a></strong>", array("class" => "align_center")); $table->construct_row(); } }@@ -286,11 +286,11 @@ // Recommended themes = Default; Otherwise search results & pagination if($mybb->request_method == "post") {- $table->output("<span style=\"float: right;\"><small><a href=\"http://community.mybb.com/mods.php?action=browse&category=themes\" target=\"_blank\">{$lang->browse_all_themes}</a></small></span>".$lang->sprintf($lang->browse_results_for_mybb, $mybb->version));+ $table->output("<span style=\"float: right;\"><small><a href=\"https://community.mybb.com/mods.php?action=browse&category=themes\" target=\"_blank\">{$lang->browse_all_themes}</a></small></span>".$lang->sprintf($lang->browse_results_for_mybb, $mybb->version)); } else {- $table->output("<span style=\"float: right;\"><small><a href=\"http://community.mybb.com/mods.php?action=browse&category=themes\" target=\"_blank\">{$lang->browse_all_themes}</a></small></span>".$lang->sprintf($lang->recommended_themes_for_mybb, $mybb->version));+ $table->output("<span style=\"float: right;\"><small><a href=\"https://community.mybb.com/mods.php?action=browse&category=themes\" target=\"_blank\">{$lang->browse_all_themes}</a></small></span>".$lang->sprintf($lang->recommended_themes_for_mybb, $mybb->version)); } echo "<br />".draw_admin_pagination($mybb->input['page'], 15, $tree['results']['attributes']['total'], "index.php?module=style-themes&action=browse{$keywords}&page={page}");@@ -2242,7 +2242,7 @@ $form->output_submit_wrapper($buttons); - echo '<script type="text/javascript" src="./jscripts/themes.js?ver=1804"></script>';+ echo '<script type="text/javascript" src="./jscripts/themes.js?ver=1808"></script>'; echo '<script type="text/javascript"> $(document).ready(function() {@@ -2348,7 +2348,7 @@ <script src="./jscripts/codemirror/mode/css/css.js"></script> <script src="./jscripts/codemirror/addon/dialog/dialog.js"></script> <script src="./jscripts/codemirror/addon/search/searchcursor.js"></script>-<script src="./jscripts/codemirror/addon/search/search.js"></script>+<script src="./jscripts/codemirror/addon/search/search.js?ver=1808"></script> '; } @@ -2624,7 +2624,7 @@ <script src="./jscripts/codemirror/mode/css/css.js"></script> <script src="./jscripts/codemirror/addon/dialog/dialog.js"></script> <script src="./jscripts/codemirror/addon/search/searchcursor.js"></script>-<script src="./jscripts/codemirror/addon/search/search.js"></script>+<script src="./jscripts/codemirror/addon/search/search.js?ver=1808"></script> '; } @@ -2887,7 +2887,7 @@ });</script>'; } - echo '<script type="text/javascript" src="./jscripts/themes.js?ver=1804"></script>';+ echo '<script type="text/javascript" src="./jscripts/themes.js?ver=1808"></script>'; echo '<script type="text/javascript" src="./jscripts/theme_properties.js"></script>'; echo '<script type="text/javascript"> $(function() {
# Security Analysis of Diff
## Vulnerability 1
**Vulnerability Existed:** yes
**Insecure Transport (HTTP) - CWE-319** - CWE-319 - admin/modules/style/themes.php [171, 217, 219, 289, 293]
**Old Code:**
```php
$contents = fetch_remote_file("http://community.mybb.com/xmlbrowse.php?type=themes&version={$search_version}{$keywords}{$url_page}", $post_data);
```
```php
$table->construct_cell("<img src=\"http://community.mybb.com/{$result['thumbnail']['value']}\" alt=\"{$lang->theme_thumbnail}\" title=\"{$lang->theme_thumbnail}\"/>", array("class" => "align_center", "width" => 100));
```
```php
$table->construct_cell("<strong><a href=\"http://community.mybb.com/{$result['download_url']['value']}\" target=\"_blank\">{$lang->download}</a></strong>", array("class" => "align_center"));
```
```php
$table->output("<span style=\"float: right;\"><small><a href=\"http://community.mybb.com/mods.php?action=browse&category=themes\" target=\"_blank\">{$lang->browse_all_themes}</a></small></span>".$lang->sprintf($lang->browse_results_for_mybb, $mybb->version));
```
**Fixed Code:**
```php
$contents = fetch_remote_file("https://community.mybb.com/xmlbrowse.php?type=themes&version={$search_version}{$keywords}{$url_page}", $post_data);
```
```php
$table->construct_cell("<img src=\"https://community.mybb.com/{$result['thumbnail']['value']}\" alt=\"{$lang->theme_thumbnail}\" title=\"{$lang->theme_thumbnail}\"/>", array("class" => "align_center", "width" => 100));
```
```php
$table->construct_cell("<strong><a href=\"https://community.mybb.com/{$result['download_url']['value']}\" target=\"_blank\">{$lang->download}</a></strong>", array("class" => "align_center"));
```
```php
$table->output("<span style=\"float: right;\"><small><a href=\"https://community.mybb.com/mods.php?action=browse&category=themes\" target=\"_blank\">{$lang->browse_all_themes}</a></small></span>".$lang->sprintf($lang->browse_results_for_mybb, $mybb->version));
```
**Explanation:**
The vulnerability is the use of unencrypted HTTP protocol to fetch remote content and embed URLs from the MyBB community site. This creates multiple security risks:
1. **Remote Content Fetching (line 171)**: Using HTTP to fetch XML theme data via `fetch_remote_file()` allows man-in-the-middle (MITM) attackers to intercept and modify the theme metadata before it's processed, potentially injecting malicious themes or data.
2. **Image and Download URLs (lines 217, 219)**: Embedding HTTP URLs for theme thumbnails and download links allows attackers to intercept these requests and inject malicious content or serve compromised theme files to administrators.
3. **External Links (lines 289, 293)**: HTTP links in the UI allow attackers to perform MITM attacks on users clicking these links.
The fix upgrades all URLs from HTTP to HTTPS, ensuring encrypted transport and preventing MITM attacks. This protects the integrity of theme data and downloaded files.
---
## Vulnerability 2
**Vulnerability Existed:** not sure
**Cache Poisoning / Version Mismatch - CWE-497** - CWE-497 - admin/modules/style/themes.php [2245, 2351, 2627, 2890]
**Old Code:**
```php
echo '<script type="text/javascript" src="./jscripts/themes.js?ver=1804"></script>';
```
```php
<script src="./jscripts/codemirror/addon/search/search.js"></script>
```
**Fixed Code:**
```php
echo '<script type="text/javascript" src="./jscripts/themes.js?ver=1808"></script>';
```
```php
<script src="./jscripts/codemirror/addon/search/search.js?ver=1808"></script>
```
**Explanation:**
The version parameter updates from 1804 to 1808 serve as cache-busting identifiers. Without these version parameters (or with outdated ones), browsers may serve cached versions of JavaScript files from a previous MyBB release. This could cause:
1. **Functional issues**: Old JavaScript logic may not work with new HTML/backend changes
2. **Security issues**: If the old version had security vulnerabilities that were patched in 1808, users would still execute the vulnerable code
3. **Inconsistent behavior**: Mismatched versions between code and JavaScript can lead to unexpected interactions
The fix ensures that when updating to version 1808, all JavaScript files are properly cache-busted and the latest versions are loaded. This is a good practice for preventing stale script execution, though the security impact depends on whether actual vulnerabilities were fixed between these versions.
--- cache/mybb_mybb_1807/admin/modules/tools/adminlog.php 2025-12-06 11:32:55.122121849 +0000+++ cache/mybb_mybb_1808/admin/modules/tools/adminlog.php 2025-12-06 11:32:55.918173251 +0000@@ -102,7 +102,7 @@ "); while($user = $db->fetch_array($query)) {- $user_options[$user['uid']] = $user['username'];+ $user_options[$user['uid']] = htmlspecialchars_uni($user['username']); } $module_options = array();@@ -238,6 +238,7 @@ { $information = ''; $trow = alt_trow();+ $logitem['username'] = htmlspecialchars_uni($logitem['username']); $username = format_name($logitem['username'], $logitem['usergroup'], $logitem['displaygroup']); $logitem['data'] = my_unserialize($logitem['data']);@@ -283,7 +284,7 @@ "); while($user = $db->fetch_array($query)) {- $user_options[$user['uid']] = $user['username'];+ $user_options[$user['uid']] = htmlspecialchars_uni($user['username']); } $module_options = array();
# Security Analysis Vulnerability Existed: **yes** **Cross-Site Scripting (XSS) - CWE-79** - admin/modules/tools/adminlog.php [Lines 105, 241, 286] **Old Code:** ```php $user_options[$user['uid']] = $user['username']; ``` **Fixed Code:** ```php $user_options[$user['uid']] = htmlspecialchars_uni($user['username']); ``` **Explanation:** The vulnerability is a Stored XSS issue where usernames retrieved from the database are directly output to HTML without proper escaping. An attacker with the ability to set a malicious username could inject JavaScript code that executes in the admin panel when viewing the admin log. The fix applies `htmlspecialchars_uni()` to encode HTML special characters, preventing the injected code from being interpreted as executable JavaScript. This is a critical fix applied consistently across three locations where usernames are used in dropdown options and display contexts. --- **Additional Context:** - Line 105: Username stored in dropdown options without escaping - Line 241: Username escaping added before being passed to `format_name()` function - Line 286: Duplicate fix applied at another location where the same pattern existed The use of `htmlspecialchars_uni()` (rather than standard `htmlspecialchars()`) suggests this is MyBB's custom function that handles Unicode characters properly while escaping HTML entities.
--- cache/mybb_mybb_1807/admin/modules/tools/file_verification.php 2025-12-06 11:32:55.122121849 +0000+++ cache/mybb_mybb_1808/admin/modules/tools/file_verification.php 2025-12-06 11:32:55.918173251 +0000@@ -36,7 +36,7 @@ $page->output_header($lang->file_verification." - ".$lang->checking); - $file = explode("\n", fetch_remote_file("http://www.mybb.com/checksums/release_mybb_{$mybb->version_code}.txt"));+ $file = explode("\n", fetch_remote_file("https://mybb.com/checksums/release_mybb_{$mybb->version_code}.txt")); if(strstr($file[0], "<?xml") !== false || empty($file[0])) {@@ -125,4 +125,3 @@ $page->output_confirm_action("index.php?module=tools-file_verification", $lang->file_verification_message, $lang->file_verification); }-
Vulnerability Existed: no
Man-in-the-Middle (MitM) Attack / Unencrypted Communication - CWE-295 - admin/modules/tools/file_verification.php (Line 39)
Old Code:
```php
$file = explode("\n", fetch_remote_file("http://www.mybb.com/checksums/release_mybb_{$mybb->version_code}.txt"));
```
Fixed Code:
```php
$file = explode("\n", fetch_remote_file("https://mybb.com/checksums/release_mybb_{$mybb->version_code}.txt"));
```
Explanation:
This change upgrades an insecure HTTP connection to a secure HTTPS connection when fetching remote checksums. The old code used unencrypted HTTP, which exposed the checksum file transfer to potential Man-in-the-Middle attacks where an attacker could intercept and modify the checksums. This would allow an attacker to serve tampered files while the verification process would incorrectly validate them against the forged checksums. The fix eliminates this vulnerability by enforcing encrypted HTTPS communication and also corrects the domain from "www.mybb.com" to "mybb.com", ensuring the checksum verification process is secure.
--- cache/mybb_mybb_1807/admin/modules/tools/maillogs.php 2025-12-06 11:32:55.122121849 +0000+++ cache/mybb_mybb_1808/admin/modules/tools/maillogs.php 2025-12-06 11:32:55.918173251 +0000@@ -430,7 +430,7 @@ { $from_type = "email"; }- $form_container->output_row($lang->from, "", $form->generate_select_box('from_type', $user_email, $from_type)." ".$form->generate_text_box('from_value', $from_filter, array('id' => 'from_value')), 'from_value');+ $form_container->output_row($lang->from, "", $form->generate_select_box('from_type', $user_email, $from_type)." ".$form->generate_text_box('from_value', htmlspecialchars_uni($from_filter), array('id' => 'from_value')), 'from_value'); if($to_username) { $to_type = "user";@@ -439,7 +439,7 @@ { $to_type = "email"; }- $form_container->output_row($lang->to, "", $form->generate_select_box('to_type', $user_email, $to_type)." ".$form->generate_text_box('to_value', $to_filter, array('id' => 'to_value')), 'to_value');+ $form_container->output_row($lang->to, "", $form->generate_select_box('to_type', $user_email, $to_type)." ".$form->generate_text_box('to_value', htmlspecialchars_uni($to_filter), array('id' => 'to_value')), 'to_value'); $form_container->end(); $buttons = array(); $buttons[] = $form->generate_submit_button($lang->filter_user_email_log);
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - admin/modules/tools/maillogs.php [433, 442]
Old Code:
```php
$form->generate_text_box('from_value', $from_filter, array('id' => 'from_value'))
$form->generate_text_box('to_value', $to_filter, array('id' => 'to_value'))
```
Fixed Code:
```php
$form->generate_text_box('from_value', htmlspecialchars_uni($from_filter), array('id' => 'from_value'))
$form->generate_text_box('to_value', htmlspecialchars_uni($to_filter), array('id' => 'to_value'))
```
Explanation:
The variables `$from_filter` and `$to_filter` contain user-supplied filter values that are displayed in form input fields without HTML encoding. An attacker could inject malicious JavaScript by submitting filter parameters with payload content (e.g., `"><script>alert('xss')</script>`). When the form is redisplayed with these filters, the unescaped values would execute in the victim's browser. The fix applies `htmlspecialchars_uni()` to encode special HTML characters, preventing the injected code from being interpreted as executable script. This is a reflected XSS vulnerability in a form filter mechanism.
--- cache/mybb_mybb_1807/admin/modules/tools/modlog.php 2025-12-06 11:32:55.122121849 +0000+++ cache/mybb_mybb_1808/admin/modules/tools/modlog.php 2025-12-06 11:32:55.918173251 +0000@@ -105,7 +105,7 @@ "); while($user = $db->fetch_array($query)) {- $user_options[$user['uid']] = $user['username'];+ $user_options[$user['uid']] = htmlspecialchars_uni($user['username']); } $form = new Form("index.php?module=tools-modlog&action=prune", "post");@@ -240,7 +240,7 @@ $logitem['action'] = htmlspecialchars_uni($logitem['action']); $logitem['dateline'] = my_date('relative', $logitem['dateline']); $trow = alt_trow();- $username = format_name($logitem['username'], $logitem['usergroup'], $logitem['displaygroup']);+ $username = format_name(htmlspecialchars_uni($logitem['username']), $logitem['usergroup'], $logitem['displaygroup']); $logitem['profilelink'] = build_profile_link($username, $logitem['uid'], "_blank"); if($logitem['tsubject']) {@@ -310,7 +310,7 @@ { $selected = "selected=\"selected\""; }- $user_options[$user['uid']] = $user['username'];+ $user_options[$user['uid']] = htmlspecialchars_uni($user['username']); } $sort_by = array(
Vulnerability Existed: yes TRUE POSITIVE XSS (Cross-Site Scripting) - CWE-79 - admin/modules/tools/modlog.php [108, 243, 313] Old Code: ```php // Line 108 $user_options[$user['uid']] = $user['username']; // Line 243 $username = format_name($logitem['username'], $logitem['usergroup'], $logitem['displaygroup']); // Line 313 $user_options[$user['uid']] = $user['username']; ``` Fixed Code: ```php // Line 108 $user_options[$user['uid']] = htmlspecialchars_uni($user['username']); // Line 243 $username = format_name(htmlspecialchars_uni($logitem['username']), $logitem['usergroup'], $logitem['displaygroup']); // Line 313 $user_options[$user['uid']] = htmlspecialchars_uni($user['username']); ``` Explanation: User-supplied data (usernames from the database) was being output directly into HTML contexts without proper escaping. This creates an XSS vulnerability where a malicious username stored in the database could execute arbitrary JavaScript when the moderation log is viewed. The fix applies `htmlspecialchars_uni()` to escape special HTML characters before output, preventing the browser from interpreting username data as executable code. This is a standard output encoding defense against reflected and stored XSS attacks (CWE-79).
--- cache/mybb_mybb_1807/admin/modules/tools/spamlog.php 2025-12-06 11:32:55.122121849 +0000+++ cache/mybb_mybb_1808/admin/modules/tools/spamlog.php 2025-12-06 11:32:55.918173251 +0000@@ -279,7 +279,7 @@ $form = new Form("index.php?module=tools-spamlog", "post"); $form_container = new FormContainer($lang->filter_spam_logs);- $form_container->output_row($lang->spam_username, "", $form->generate_text_box('username', $mybb->input['username'], array('id' => 'username')), 'suername');+ $form_container->output_row($lang->spam_username, "", $form->generate_text_box('username', htmlspecialchars_uni($mybb->get_input('username')), array('id' => 'username')), 'suername'); $form_container->output_row($lang->spam_email, "", $form->generate_text_box('email', $mybb->input['email'], array('id' => 'email')), 'email'); $form_container->output_row($lang->spam_ip, "", $form->generate_text_box('ipaddress', $mybb->input['ipaddress'], array('id' => 'ipaddress')), 'ipaddress'); $form_container->output_row($lang->sort_by, "", $form->generate_select_box('sortby', $sort_by, $mybb->input['sortby'], array('id' => 'sortby'))." {$lang->in} ".$form->generate_select_box('order', $order_array, $order, array('id' => 'order'))." {$lang->order}", 'order');
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - admin/modules/tools/spamlog.php [282]
Old Code:
```php
$form->generate_text_box('username', $mybb->input['username'], array('id' => 'username'))
```
Fixed Code:
```php
$form->generate_text_box('username', htmlspecialchars_uni($mybb->get_input('username')), array('id' => 'username'))
```
Explanation:
The old code directly used `$mybb->input['username']` without any escaping when generating a text box in the form. User-supplied input from `$mybb->input['username']` could contain malicious JavaScript code that would be injected into the HTML attribute value, allowing an attacker to execute arbitrary scripts in the context of an admin's browser (Stored XSS if persisted, or Reflected XSS if passed via URL parameters).
The fix applies two important security measures:
1. **`htmlspecialchars_uni()`** - Escapes HTML special characters, converting potentially dangerous characters (like `<`, `>`, `"`, `'`) into HTML entities, preventing script injection
2. **`$mybb->get_input()`** - Uses the safer input retrieval method instead of direct array access, which may provide additional sanitization depending on the framework's implementation
This prevents the injected code from being interpreted as executable JavaScript and neutralizes the XSS vulnerability.
--- cache/mybb_mybb_1807/admin/modules/tools/system_health.php 2025-12-06 11:32:55.122121849 +0000+++ cache/mybb_mybb_1808/admin/modules/tools/system_health.php 2025-12-06 11:32:55.918173251 +0000@@ -922,7 +922,7 @@ if($errors) {- $page->output_error("<p><em>{$errors} {$lang->error_chmod}</span></strong> {$lang->chmod_info} <a href=\"http://docs.mybb.com/HowTo_Chmod.html\" target=\"_blank\">MyBB Docs</a>.</em></p>");+ $page->output_error("<p><em>{$errors} {$lang->error_chmod}</span></strong> {$lang->chmod_info} <a href=\"https://docs.mybb.com/1.8/administration/security/file-permissions\" target=\"_blank\">MyBB Docs</a>.</em></p>"); } else {
Vulnerability Existed: no
No CWE Identified - File: admin/modules/tools/system_health.php [Line 925]
Old Code:
```php
$page->output_error("<p><em>{$errors} {$lang->error_chmod}</span></strong> {$lang->chmod_info} <a href=\"http://docs.mybb.com/HowTo_Chmod.html\" target=\"_blank\">MyBB Docs</a>.</em></p>");
```
Fixed Code:
```php
$page->output_error("<p><em>{$errors} {$lang->error_chmod}</span></strong> {$lang->chmod_info} <a href=\"https://docs.mybb.com/1.8/administration/security/file-permissions\" target=\"_blank\">MyBB Docs</a>.</em></p>");
```
Explanation:
This change upgrades the documentation link from HTTP to HTTPS and updates the URL to point to a more specific documentation page. This is a security enhancement rather than a fix for an existing vulnerability. The change promotes secure communication (HTTPS) and improves the relevance of the documentation link, but the old code itself was not vulnerable to exploitation. The hardcoded URL in a static error message does not present a security risk in this context.
--- cache/mybb_mybb_1807/admin/modules/tools/warninglog.php 2025-12-06 11:32:55.122121849 +0000+++ cache/mybb_mybb_1808/admin/modules/tools/warninglog.php 2025-12-06 11:32:55.922173510 +0000@@ -110,7 +110,7 @@ $page->output_header($lang->warning_details); - $user_link = build_profile_link($user['username'], $user['uid'], "_blank");+ $user_link = build_profile_link(htmlspecialchars_uni($user['username']), $user['uid'], "_blank"); if(is_array($warn_errors)) {@@ -142,7 +142,7 @@ $table->construct_row(); } - $issuedby = build_profile_link($warning['username'], $warning['issuedby'], "_blank");+ $issuedby = build_profile_link(htmlspecialchars_uni($warning['username']), $warning['issuedby'], "_blank"); $notes = nl2br(htmlspecialchars_uni($warning['notes'])); $date_issued = my_date('relative', $warning['dateline']);@@ -215,7 +215,7 @@ { $date_revoked = my_date('relative', $warning['daterevoked']); $revoked_user = get_user($warning['revokedby']);- $revoked_by = build_profile_link($revoked_user['username'], $revoked_user['uid'], "_blank");+ $revoked_by = build_profile_link(htmlspecialchars_uni($revoked_user['username']), $revoked_user['uid'], "_blank"); $revoke_reason = nl2br(htmlspecialchars_uni($warning['revokereason'])); $revoke_table = new Table;@@ -391,7 +391,7 @@ } $trow = alt_trow();- $username = format_name($row['username'], $row['usergroup'], $row['displaygroup']);+ $username = format_name(htmlspecialchars_uni($row['username']), $row['usergroup'], $row['displaygroup']); if(!$row['uid']) { $username_link = $username;@@ -400,7 +400,7 @@ { $username_link = build_profile_link($username, $row['uid'], "_blank"); }- $mod_username = format_name($row['mod_username'], $row['mod_usergroup'], $row['mod_displaygroup']);+ $mod_username = format_name(htmlspecialchars_uni($row['mod_username']), $row['mod_usergroup'], $row['mod_displaygroup']); $mod_username_link = build_profile_link($mod_username, $row['mod_uid'], "_blank"); $issued_date = my_date('relative', $row['dateline']); $revoked_text = '';
``` Vulnerability Existed: yes TRUE POSITIVE Cross-Site Scripting (XSS) - CWE-79 - admin/modules/tools/warninglog.php [Lines 113, 145, 218, 394, 403] Old Code: $user_link = build_profile_link($user['username'], $user['uid'], "_blank"); $issuedby = build_profile_link($warning['username'], $warning['issuedby'], "_blank"); $revoked_by = build_profile_link($revoked_user['username'], $revoked_user['uid'], "_blank"); $username = format_name($row['username'], $row['usergroup'], $row['displaygroup']); $mod_username = format_name($row['mod_username'], $row['mod_usergroup'], $row['mod_displaygroup']); Fixed Code: $user_link = build_profile_link(htmlspecialchars_uni($user['username']), $user['uid'], "_blank"); $issuedby = build_profile_link(htmlspecialchars_uni($warning['username']), $warning['issuedby'], "_blank"); $revoked_by = build_profile_link(htmlspecialchars_uni($revoked_user['username']), $revoked_user['uid'], "_blank"); $username = format_name(htmlspecialchars_uni($row['username']), $row['usergroup'], $row['displaygroup']); $mod_username = format_name(htmlspecialchars_uni($row['mod_username']), $row['mod_usergroup'], $row['mod_displaygroup']); Explanation: User-controlled data from the database (usernames) was being passed directly to display functions without HTML entity encoding. While the functions `build_profile_link()` and `format_name()` may perform some escaping internally, the explicit addition of `htmlspecialchars_uni()` ensures usernames containing special characters or HTML metacharacters (e.g., `<script>`, `'`, `"`, `&`) are properly encoded before being passed to these functions. This prevents Stored XSS attacks where a malicious username could be injected and executed in the browser when the warning log is displayed. The fix properly escapes all five instances of unescaped username variables across the different warning log display contexts. ```
--- cache/mybb_mybb_1807/admin/modules/user/admin_permissions.php 2025-12-06 11:32:55.126122107 +0000+++ cache/mybb_mybb_1808/admin/modules/user/admin_permissions.php 2025-12-06 11:32:55.922173510 +0000@@ -210,7 +210,7 @@ $admin = $db->fetch_array($query); $permission_data = get_admin_permissions($uid, $admin['gid']);- $title = $admin['username'];+ $title = htmlspecialchars_uni($admin['username']); $page->add_breadcrumb_item($lang->user_permissions, "index.php?module=user-admin_permissions"); } elseif($uid < 0)@@ -489,7 +489,8 @@ } $usergroup_list = implode($lang->comma, $usergroup_list); - $table->construct_cell("<div class=\"float_right\"><img src=\"styles/{$page->style}/images/icons/{$perm_type}.png\" title=\"{$lang->perms_type_user}\" alt=\"{$perm_type}\" /></div><div><strong><a href=\"index.php?module=user-admin_permissions&action=edit&uid={$admin['uid']}\" title=\"{$lang->edit_user}\">{$admin['username']}</a></strong><br /><small>{$usergroup_list}</small></div>");+ $username = htmlspecialchars_uni($admin['username']);+ $table->construct_cell("<div class=\"float_right\"><img src=\"styles/{$page->style}/images/icons/{$perm_type}.png\" title=\"{$lang->perms_type_user}\" alt=\"{$perm_type}\" /></div><div><strong><a href=\"index.php?module=user-admin_permissions&action=edit&uid={$admin['uid']}\" title=\"{$lang->edit_user}\">{$username}</a></strong><br /><small>{$usergroup_list}</small></div>"); $table->construct_cell(my_date('relative', $admin['lastactive']), array("class" => "align_center"));
Analyzing the provided diff for security vulnerabilities:
---
**Vulnerability 1:**
Vulnerability Existed: yes
TRUE POSITIVE
**Cross-Site Scripting (XSS) - CWE-79** - admin/modules/user/admin_permissions.php - Line 213
Old Code:
```php
$title = $admin['username'];
```
Fixed Code:
```php
$title = htmlspecialchars_uni($admin['username']);
```
Explanation:
The `$admin['username']` variable was being directly assigned to `$title` without sanitization. Since `$title` is later rendered in HTML output (via breadcrumb), an attacker-controlled username containing HTML/JavaScript could execute arbitrary scripts in the admin's browser. The fix applies `htmlspecialchars_uni()` to encode special characters, preventing XSS payload execution.
---
**Vulnerability 2:**
Vulnerability Existed: yes
TRUE POSITIVE
**Cross-Site Scripting (XSS) - CWE-79** - admin/modules/user/admin_permissions.php - Line 492-493
Old Code:
```php
$table->construct_cell("<div class=\"float_right\"><img src=\"styles/{$page->style}/images/icons/{$perm_type}.png\" title=\"{$lang->perms_type_user}\" alt=\"{$perm_type}\" /></div><div><strong><a href=\"index.php?module=user-admin_permissions&action=edit&uid={$admin['uid']}\" title=\"{$lang->edit_user}\">{$admin['username']}</a></strong><br /><small>{$usergroup_list}</small></div>");
```
Fixed Code:
```php
$username = htmlspecialchars_uni($admin['username']);
$table->construct_cell("<div class=\"float_right\"><img src=\"styles/{$page->style}/images/icons/{$perm_type}.png\" title=\"{$lang->perms_type_user}\" alt=\"{$perm_type}\" /></div><div><strong><a href=\"index.php?module=user-admin_permissions&action=edit&uid={$admin['uid']}\" title=\"{$lang->edit_user}\">{$username}</a></strong><br /><small>{$usergroup_list}</small></div>");
```
Explanation:
The `$admin['username']` variable was directly embedded in HTML output within a table cell without escaping. This creates an XSS vulnerability where malicious usernames could inject JavaScript. The fix pre-sanitizes the username using `htmlspecialchars_uni()` before embedding it in the HTML string, preventing script injection through the username field.
--- cache/mybb_mybb_1807/admin/modules/user/banning.php 2025-12-06 11:32:55.126122107 +0000+++ cache/mybb_mybb_1808/admin/modules/user/banning.php 2025-12-06 11:32:55.922173510 +0000@@ -99,7 +99,7 @@ $cache->update_reportedcontent(); // Log admin action- log_admin_action($user['uid'], $user['username']);+ log_admin_action($user['uid'], htmlspecialchars_uni($user['username'])); flash_message($lang->success_pruned, 'success'); admin_redirect("index.php?module=user-banning");@@ -154,7 +154,7 @@ $cache->update_moderators(); // Log admin action- log_admin_action($ban['uid'], $user['username']);+ log_admin_action($ban['uid'], htmlspecialchars_uni($user['username'])); flash_message($lang->success_ban_lifted, 'success'); admin_redirect("index.php?module=user-banning");@@ -241,7 +241,7 @@ $cache->update_banned(); // Log admin action- log_admin_action($ban['uid'], $user['username']);+ log_admin_action($ban['uid'], htmlspecialchars_uni($user['username'])); flash_message($lang->success_ban_updated, 'success'); admin_redirect("index.php?module=user-banning");@@ -268,7 +268,7 @@ } $form_container = new FormContainer($lang->edit_ban);- $form_container->output_row($lang->ban_username, "", $user['username']);+ $form_container->output_row($lang->ban_username, "", htmlspecialchars_uni($user['username'])); $form_container->output_row($lang->ban_reason, "", $form->generate_text_area('reason', $mybb->input['reason'], array('id' => 'reason', 'maxlength' => '255')), 'reason'); if(count($banned_groups) > 1) {@@ -285,7 +285,7 @@ { if($time != '---') {- $friendly_time = my_date("D, jS M Y @ g:ia", ban_date2timestamp($time));+ $friendly_time = my_date("D, jS M Y @ {$mybb->settings['timeformat']}", ban_date2timestamp($time)); $period = "{$period} ({$friendly_time})"; } $length_list[$time] = $period;@@ -316,7 +316,7 @@ $user = get_user_by_username($mybb->input['username'], $options); // Are we searching a user?- if(isset($mybb->input['search']) && $mybb->get_input('search') != '')+ if(isset($mybb->input['search'])) { $where_sql = 'uid=\''.(int)$user['uid'].'\''; $where_sql_full = 'WHERE b.uid=\''.(int)$user['uid'].'\'';@@ -405,7 +405,7 @@ $cache->update_banned(); // Log admin action- log_admin_action($user['uid'], $user['username'], $lifted);+ log_admin_action($user['uid'], htmlspecialchars_uni($user['username']), $lifted); flash_message($lang->success_banned, 'success'); admin_redirect("index.php?module=user-banning");@@ -463,7 +463,7 @@ // Get the banned users while($ban = $db->fetch_array($query)) {- $profile_link = build_profile_link($ban['username'], $ban['uid'], "_blank");+ $profile_link = build_profile_link(htmlspecialchars_uni($ban['username']), $ban['uid'], "_blank"); $ban_date = my_date($mybb->settings['dateformat'], $ban['dateline']); if($ban['lifted'] == 'perm' || $ban['lifted'] == '' || $ban['bantime'] == 'perm' || $ban['bantime'] == '---') {@@ -497,7 +497,7 @@ { if($ban['admin'] == 0) {- $ban['adminuser'] = "MyBB System";+ $ban['adminuser'] = $lang->mybb_engine; } else {@@ -545,7 +545,7 @@ { if($time != "---") {- $friendly_time = my_date("D, jS M Y @ g:ia", ban_date2timestamp($time));+ $friendly_time = my_date("D, jS M Y @ {$mybb->settings['timeformat']}", ban_date2timestamp($time)); $period = "{$period} ({$friendly_time})"; } $length_list[$time] = $period;@@ -598,7 +598,7 @@ </script>'; $buttons[] = $form->generate_submit_button($lang->ban_user);- $buttons[] = $form->generate_submit_button($lang->search_user, array('name' => 'search'));+ $buttons[] = $form->generate_submit_button($lang->search_for_a_user, array('name' => 'search')); $form->output_submit_wrapper($buttons); $form->end();
# Security Analysis of admin/modules/user/banning.php
## Vulnerability 1: Cross-Site Scripting (XSS) via Username Output
**Vulnerability Existed:** yes
**Cross-Site Scripting (XSS) - CWE-79 - admin/modules/user/banning.php [102, 157, 244, 271, 408, 466]**
**Old Code:**
```php
log_admin_action($user['uid'], $user['username']);
// and
$form_container->output_row($lang->ban_username, "", $user['username']);
// and
$profile_link = build_profile_link($ban['username'], $ban['uid'], "_blank");
```
**Fixed Code:**
```php
log_admin_action($user['uid'], htmlspecialchars_uni($user['username']));
// and
$form_container->output_row($lang->ban_username, "", htmlspecialchars_uni($user['username']));
// and
$profile_link = build_profile_link(htmlspecialchars_uni($ban['username']), $ban['uid'], "_blank");
```
**Explanation:**
Usernames from the database were being output to HTML without proper escaping. An attacker with the ability to create or modify usernames in the database could inject malicious JavaScript code that would execute in the context of admin users viewing the banning module. The fix applies `htmlspecialchars_uni()` (MyBB's HTML encoding function) to escape special characters before output, preventing XSS payload execution.
---
## Vulnerability 2: Hardcoded Time Format Vulnerability
**Vulnerability Existed:** yes
**Improper Neutralization of Input During Web Page Generation - CWE-79 - admin/modules/user/banning.php [288, 548]**
**Old Code:**
```php
$friendly_time = my_date("D, jS M Y @ g:ia", ban_date2timestamp($time));
```
**Fixed Code:**
```php
$friendly_time = my_date("D, jS M Y @ {$mybb->settings['timeformat']}", ban_date2timestamp($time));
```
**Explanation:**
The hardcoded time format `"g:ia"` ignored user/site settings for time display. While this itself isn't a direct vulnerability, using configurable time format from `$mybb->settings['timeformat']` is a best practice. This fix respects admin-configured time formats and prevents potential inconsistencies or injection vectors if the time format could be controlled externally.
---
## Non-Vulnerability 3: Input Validation Change
**Vulnerability Existed:** no
**Input Validation Logic - No CWE - admin/modules/user/banning.php [319]**
**Old Code:**
```php
if(isset($mybb->input['search']) && $mybb->get_input('search') != '')
```
**Fixed Code:**
```php
if(isset($mybb->input['search']))
```
**Explanation:**
This change removes the redundant empty string check. The `isset()` check is sufficient to determine if the search parameter exists. This is not a security vulnerability fix but rather a code simplification. The original code was overly defensive; the fix correctly identifies that the presence of the parameter is what matters for the search logic.
---
## Non-Vulnerability 4: Localization String Update
**Vulnerability Existed:** no
**Localization Update - No CWE - admin/modules/user/banning.php [598]**
**Old Code:**
```php
$buttons[] = $form->generate_submit_button($lang->search_user, array('name' => 'search'));
```
**Fixed Code:**
```php
$buttons[] = $form->generate_submit_button($lang->search_for_a_user, array('name' => 'search'));
```
**Explanation:**
This is a localization/UI text update changing the button label from `$lang->search_user` to `$lang->search_for_a_user`. This is not a security fix but rather an improvement to user-facing text for clarity.
---
## Non-Vulnerability 5: Localization String Update (System Label)
**Vulnerability Existed:** no
**Localization Update - No CWE - admin/modules/user/banning.php [501]**
**Old Code:**
```php
$ban['adminuser'] = "MyBB System";
```
**Fixed Code:**
```php
$ban['adminuser'] = $lang->mybb_engine;
```
**Explanation:**
This change replaces a hardcoded English string with a localized language constant `$lang->mybb_engine`, improving internationalization. This is not a security vulnerability but a UX/localization improvement.
---
## Summary
The patch addresses **one primary security vulnerability**: **XSS via unescaped username output** in multiple locations throughout the banning module. This is a significant vulnerability that could allow authenticated database-level attackers to execute arbitrary JavaScript in admin contexts. The fix consistently applies HTML entity encoding via `htmlspecialchars_uni()` to all user-controlled output points. Additional changes are code quality improvements and localization enhancements.
--- cache/mybb_mybb_1807/admin/modules/user/groups.php 2025-12-06 11:32:55.126122107 +0000+++ cache/mybb_mybb_1808/admin/modules/user/groups.php 2025-12-06 11:32:55.922173510 +0000@@ -64,8 +64,8 @@ "candeletereputations" => 1, "reputationpower" => 1, "maxreputationsday" => 5,- "maxreputationsperuser" => 5,- "maxreputationsperthread" => 5,+ "maxreputationsperuser" => 0,+ "maxreputationsperthread" => 0, "candisplaygroup" => 0, "attachquota" => 5000, "cancustomtitle" => 0,@@ -283,7 +283,7 @@ while($request = $db->fetch_array($query)) { $table->construct_cell($form->generate_check_box("users[]", $request['uid'], ""));- $table->construct_cell("<strong>".build_profile_link($request['username'], $request['uid'], "_blank")."</strong>");+ $table->construct_cell("<strong>".build_profile_link(htmlspecialchars_uni($request['username']), $request['uid'], "_blank")."</strong>"); $table->construct_cell(htmlspecialchars_uni($request['reason'])); $table->construct_cell(my_date('relative', $request['dateline']), array('class' => 'align_center')); @@ -364,9 +364,10 @@ $cache->update_groupleaders(); // Log admin action- log_admin_action($user['uid'], $user['username'], $group['gid'], htmlspecialchars_uni($group['title']));+ log_admin_action($user['uid'], htmlspecialchars_uni($user['username']), $group['gid'], htmlspecialchars_uni($group['title'])); - flash_message("{$user['username']} ".$lang->success_user_made_leader, 'success');+ $username = htmlspecialchars_uni($user['username']);+ flash_message("{$username} ".$lang->success_user_made_leader, 'success'); admin_redirect("index.php?module=user-groups&action=leaders&gid={$group['gid']}"); } else@@ -481,7 +482,7 @@ } $form_container = new FormContainer($lang->add_group_leader.' '.htmlspecialchars_uni($group['title']));- $form_container->output_row($lang->username." <em>*</em>", "", $form->generate_text_box('username', $mybb->input['username'], array('id' => 'username')), 'username');+ $form_container->output_row($lang->username." <em>*</em>", "", $form->generate_text_box('username', htmlspecialchars_uni($mybb->get_input('username')), array('id' => 'username')), 'username'); $form_container->output_row($lang->can_manage_group_members, $lang->can_manage_group_members_desc, $form->generate_yes_no_radio('canmanagemembers', $mybb->input['canmanagemembers'])); $form_container->output_row($lang->can_manage_group_join_requests, $lang->can_manage_group_join_requests_desc, $form->generate_yes_no_radio('canmanagerequests', $mybb->input['canmanagerequests'])); $form_container->output_row($lang->can_invite_group_members, $lang->can_invite_group_members_desc, $form->generate_yes_no_radio('caninvitemembers', $mybb->input['caninvitemembers']));@@ -571,7 +572,7 @@ $cache->update_groupleaders(); // Log admin action- log_admin_action($leader['uid'], $leader['username'], $group['gid'], htmlspecialchars_uni($group['title']));+ log_admin_action($leader['uid'], htmlspecialchars_uni($leader['username']), $group['gid'], htmlspecialchars_uni($group['title'])); flash_message($lang->success_group_leader_deleted, 'success'); admin_redirect("index.php?module=user-groups&action=leaders&gid={$group['gid']}");@@ -618,7 +619,7 @@ $cache->update_groupleaders(); // Log admin action- log_admin_action($leader['uid'], $leader['username'], $group['gid'], htmlspecialchars_uni($group['title']));+ log_admin_action($leader['uid'], htmlspecialchars_uni($leader['username']), $group['gid'], htmlspecialchars_uni($group['title'])); flash_message($lang->success_group_leader_updated, 'success'); admin_redirect("index.php?module=user-groups&action=leaders&gid={$group['gid']}");@@ -630,6 +631,7 @@ } $page->add_breadcrumb_item($lang->group_leaders_for.' '.htmlspecialchars_uni($group['title']), "index.php?module=user-groups&action=leaders&gid={$group['gid']}");+ $leader['username'] = htmlspecialchars_uni($leader['username']); $page->add_breadcrumb_item($lang->edit_leader." {$leader['username']}"); $page->output_header($lang->edit_group_leader);@@ -1147,6 +1149,7 @@ $form->generate_check_box("candeletereputations", 1, $lang->can_delete_own_reputation, array("checked" => $mybb->input['candeletereputations'])), "{$lang->points_to_award_take}<br /><small class=\"input\">{$lang->points_to_award_take_desc}</small><br />".$form->generate_numeric_field('reputationpower', $mybb->input['reputationpower'], array('id' => 'reputationpower', 'class' => 'field50', 'min' => 0)), "{$lang->max_reputations_perthread}<br /><small class=\"input\">{$lang->max_reputations_perthread_desc}</small><br />".$form->generate_numeric_field('maxreputationsperthread', $mybb->input['maxreputationsperthread'], array('id' => 'maxreputationsperthread', 'class' => 'field50', 'min' => 0)),+ "{$lang->max_reputations_peruser}<br /><small class=\"input\">{$lang->max_reputations_peruser_desc}</small><br />".$form->generate_numeric_field('maxreputationsperuser', $mybb->input['maxreputationsperuser'], array('id' => 'maxreputationsperuser', 'class' => 'field50', 'min' => 0)), "{$lang->max_reputations_daily}<br /><small class=\"input\">{$lang->max_reputations_daily_desc}</small><br />".$form->generate_numeric_field('maxreputationsday', $mybb->input['maxreputationsday'], array('id' => 'maxreputationsday', 'class' => 'field50', 'min' => 0)) ); $form_container->output_row($lang->reputation_system, "", "<div class=\"group_settings_bit\">".implode("</div><div class=\"group_settings_bit\">", $reputation_options)."</div>");@@ -1440,7 +1443,7 @@ "); while($leader = $db->fetch_array($query)) {- $leaders[$leader['gid']][] = build_profile_link($leader['username'], $leader['uid'], "_blank");+ $leaders[$leader['gid']][] = build_profile_link(htmlspecialchars_uni($leader['username']), $leader['uid'], "_blank"); } $form_container = new FormContainer($lang->user_groups);
I'll analyze this code diff for security vulnerabilities following the specified format.
---
**Vulnerability 1:**
Vulnerability Existed: yes
**Cross-Site Scripting (XSS) - CWE-79** - admin/modules/user/groups.php - Line 286
**Old Code:**
```php
$table->construct_cell("<strong>".build_profile_link($request['username'], $request['uid'], "_blank")."</strong>");
```
**Fixed Code:**
```php
$table->construct_cell("<strong>".build_profile_link(htmlspecialchars_uni($request['username']), $request['uid'], "_blank")."</strong>");
```
Explanation:
The username from the database was being passed directly to `build_profile_link()` without HTML encoding. If a username contains special characters or malicious HTML/JavaScript, it could be rendered without escaping, leading to XSS. The fix wraps the username with `htmlspecialchars_uni()` to properly escape HTML entities.
---
**Vulnerability 2:**
Vulnerability Existed: yes
FALSE POSITIVE
**Cross-Site Scripting (XSS) - CWE-79** - admin/modules/user/groups.php - Line 367
**Old Code:**
```php
log_admin_action($user['uid'], $user['username'], $group['gid'], htmlspecialchars_uni($group['title']));
flash_message("{$user['username']} ".$lang->success_user_made_leader, 'success');
```
**Fixed Code:**
```php
log_admin_action($user['uid'], htmlspecialchars_uni($user['username']), $group['gid'], htmlspecialchars_uni($group['title']));
$username = htmlspecialchars_uni($user['username']);
flash_message("{$username} ".$lang->success_user_made_leader, 'success');
```
Explanation:
The username was being logged and displayed in a flash message without HTML encoding. This could allow XSS if usernames contain malicious content. The fix encodes the username before passing it to both `log_admin_action()` and `flash_message()`.
---
**Vulnerability 3:**
Vulnerability Existed: yes
TRUE POSITIVE
**Cross-Site Scripting (XSS) - CWE-79** - admin/modules/user/groups.php - Line 485
**Old Code:**
```php
$form->generate_text_box('username', $mybb->input['username'], array('id' => 'username'))
```
**Fixed Code:**
```php
$form->generate_text_box('username', htmlspecialchars_uni($mybb->get_input('username')), array('id' => 'username'))
```
Explanation:
User input from `$mybb->input['username']` was being directly inserted into a form field without escaping. An attacker could inject malicious HTML/JavaScript that would be reflected in the form. The fix encodes the input with `htmlspecialchars_uni()` to prevent XSS.
---
**Vulnerability 4:**
Vulnerability Existed: yes
TRUE POSITIVE
**Cross-Site Scripting (XSS) - CWE-79** - admin/modules/user/groups.php - Line 575
**Old Code:**
```php
log_admin_action($leader['uid'], $leader['username'], $group['gid'], htmlspecialchars_uni($group['title']));
```
**Fixed Code:**
```php
log_admin_action($leader['uid'], htmlspecialchars_uni($leader['username']), $group['gid'], htmlspecialchars_uni($group['title']));
```
Explanation:
Similar to Vulnerability 2, the username was passed to `log_admin_action()` without HTML encoding. The fix wraps it with `htmlspecialchars_uni()` to prevent XSS in log entries.
---
**Vulnerability 5:**
Vulnerability Existed: yes
FALSE POSITIVE
**Cross-Site Scripting (XSS) - CWE-79** - admin/modules/user/groups.php - Line 622
**Old Code:**
```php
log_admin_action($leader['uid'], $leader['username'], $group['gid'], htmlspecialchars_uni($group['title']));
```
**Fixed Code:**
```php
log_admin_action($leader['uid'], htmlspecialchars_uni($leader['username']), $group['gid'], htmlspecialchars_uni($group['title']));
```
Explanation:
Same XSS vulnerability in `log_admin_action()`. The username is encoded in the fix to prevent XSS.
---
**Vulnerability 6:**
Vulnerability Existed: yes
TRUE POSITIVE
**Cross-Site Scripting (XSS) - CWE-79** - admin/modules/user/groups.php - Line 634
**Old Code:**
```php
$page->add_breadcrumb_item($lang->edit_leader." {$leader['username']}");
```
**Fixed Code:**
```php
$leader['username'] = htmlspecialchars_uni($leader['username']);
$page->add_breadcrumb_item($lang->edit_leader." {$leader['username']}");
```
Explanation:
The username was being directly interpolated into a breadcrumb without escaping. The fix pre-encodes the username before using it in the breadcrumb display.
---
**Vulnerability 7:**
Vulnerability Existed: yes
TRUE POSITIVE
**Cross-Site Scripting (XSS) - CWE-79** - admin/modules/user/groups.php - Line 1443
**Old Code:**
```php
$leaders[$leader['gid']][] = build_profile_link($leader['username'], $leader['uid'], "_blank");
```
**Fixed Code:**
```php
$leaders[$leader['gid']][] = build_profile_link(htmlspecialchars_uni($leader['username']), $leader['uid'], "_blank");
```
Explanation:
The leader username was passed to `build_profile_link()` without encoding. The fix properly escapes the username with `htmlspecialchars_uni()` to prevent XSS.
---
**Non-Vulnerability Change:**
Lines 67-68: The change from `5` to `0` for `maxreputationsperuser` and `maxreputationsperthread` is a configuration/logic change, not a security fix. This disables certain reputation features but is not a vulnerability fix.
--- cache/mybb_mybb_1807/admin/modules/user/mass_mail.php 2025-12-06 11:32:55.126122107 +0000+++ cache/mybb_mybb_1808/admin/modules/user/mass_mail.php 2025-12-06 11:32:55.926173768 +0000@@ -82,6 +82,8 @@ $html_personalisation = substr($html_personalisation, 0, -2)."');\n// --></script>\n"; $text_personalisation = substr($text_personalisation, 0, -2)."');\n// --></script>\n"; + $localized_time_offset = $mybb->user['timezone']*3600 + $mybb->user['dst']*3600;+ // All done here if($mybb->request_method == "post") {@@ -93,7 +95,7 @@ // Delivering in the future else {- if(strstr($mybb->input['deliverytime_time'], "pm"))+ if(stristr($mybb->input['deliverytime_time'], "pm")) { $mybb->input['deliveryhour'] += 12; }@@ -104,7 +106,7 @@ $exploded = explode(' ', $exploded[1]); $mybb->input['deliveryminute'] = (int)$exploded[0]; - $delivery_date = gmmktime($mybb->input['deliveryhour'], $mybb->input['deliveryminute'], 0, $mybb->input['endtime_month'], $mybb->input['endtime_day'], $mybb->input['endtime_year']) + $mybb->user['timezone']*3600;+ $delivery_date = gmmktime($mybb->input['deliveryhour'], $mybb->input['deliveryminute'], 0, $mybb->input['endtime_month'], $mybb->input['endtime_day'], $mybb->input['endtime_year']) - $localized_time_offset; if($delivery_date <= TIME_NOW) { $errors[] = $lang->error_only_in_future;@@ -222,15 +224,15 @@ } else {+ // correct date by timezone and dst+ $offset = $input['delivery_type'] = "future";- $time = date("d-n-Y-h-i-a", $email['senddate']);+ $time = gmdate("d-n-Y", $email['senddate'] + $localized_time_offset); $time = explode('-', $time);- $input['deliveryhour'] = (int)$time[3];- $input['deliveryminute'] = (int)$time[4]; $input['deliverymonth'] = (int)$time[1]; $input['deliveryday'] = (int)$time[0]; $input['deliveryyear'] = (int)$time[2];- $input['deliverymeridiem'] = $time[5];+ $input['endtime_time'] = gmdate($mybb->settings['timeformat'], $email['senddate'] + $localized_time_offset); $delivery_type_checked['future'] = " checked=\"checked\""; } }@@ -240,37 +242,15 @@ $delivery_type_checked['now'] = " checked=\"checked\""; } }-- if($input['deliveryhour'])- {- $input['endtime_time'] = (int)$input['deliveryhour'].":";- }- else- {- $input['endtime_time'] = "12:";- }-- if($input['deliveryminute'])- {- $input['endtime_time'] .= (int)$input['deliveryminute']." ";- }- else- {- $input['endtime_time'] .= "00 ";- }-- if($input['deliverymeridiem'])- {- $input['endtime_time'] .= $input['deliverymeridiem'];- }- else+ + if(!$input['endtime_time']) {- $input['endtime_time'] .= "am";+ $input['endtime_time'] = gmdate($mybb->settings['timeformat'], TIME_NOW + $localized_time_offset); } if(!$input['deliveryyear']) {- $enddateyear = gmdate('Y', TIME_NOW);+ $enddateyear = gmdate('Y', TIME_NOW + $localized_time_offset); } else {@@ -279,7 +259,7 @@ if(!$input['deliverymonth']) {- $input['enddatemonth'] = gmdate('n', TIME_NOW);+ $input['enddatemonth'] = gmdate('n', TIME_NOW + $localized_time_offset); } else {@@ -288,7 +268,7 @@ if(!$input['deliveryday']) {- $input['enddateday'] = gmdate('j', TIME_NOW);+ $input['enddateday'] = gmdate('j', TIME_NOW + $localized_time_offset); } else {@@ -557,7 +537,7 @@ $form_container = new FormContainer("{$lang->edit_mass_mail}: {$lang->define_the_recipients}"); - $form_container->output_row($lang->username_contains, "", $form->generate_text_box('conditions[username]', $input['conditions']['username'], array('id' => 'username')), 'username');+ $form_container->output_row($lang->username_contains, "", $form->generate_text_box('conditions[username]', htmlspecialchars_uni($input['conditions']['username']), array('id' => 'username')), 'username'); $form_container->output_row($lang->email_addr_contains, "", $form->generate_text_box('conditions[email]', $input['conditions']['email'], array('id' => 'email')), 'email'); $query = $db->simple_select("usergroups", "gid, title", "gid != '1'", array('order_by' => 'title'));@@ -634,6 +614,8 @@ $text_personalisation = substr($text_personalisation, 0, -2)."');\n// --></script>\n"; $plugins->run_hooks("admin_user_mass_email_send_start");+ + $localized_time_offset = $mybb->user['timezone']*3600 + $mybb->user['dst']*3600; if($mybb->input['step'] == 4) {@@ -648,7 +630,7 @@ // Delivering in the future else {- if(strstr($mybb->input['deliverytime_time'], "pm"))+ if(stristr($mybb->input['deliverytime_time'], "pm")) { $mybb->input['deliveryhour'] += 12; }@@ -659,7 +641,7 @@ $exploded = explode(' ', $exploded[1]); $mybb->input['deliveryminute'] = (int)$exploded[0]; - $delivery_date = gmmktime($mybb->input['deliveryhour'], $mybb->input['deliveryminute'], 0, $mybb->input['endtime_month'], $mybb->input['endtime_day'], $mybb->input['endtime_year']) + $mybb->user['timezone']*3600;+ $delivery_date = gmmktime($mybb->input['deliveryhour'], $mybb->input['deliveryminute'], 0, $mybb->input['endtime_month'], $mybb->input['endtime_day'], $mybb->input['endtime_year'])- $localized_time_offset; if($delivery_date <= TIME_NOW) { $errors[] = $lang->error_only_in_future;@@ -707,14 +689,12 @@ else { $input['delivery_type'] = "future";- $time = date("d-n-Y-h-i-a", $email['senddate']);+ $time = gmdate("d-n-Y", $email['senddate'] + $localized_time_offset); $time = explode('-', $time);- $input['deliveryhour'] = (int)$time[3];- $input['deliveryminute'] = (int)$time[4]; $input['deliverymonth'] = (int)$time[1]; $input['deliveryday'] = (int)$time[0]; $input['deliveryyear'] = (int)$time[2];- $input['deliverymeridiem'] = $time[5];+ $input['endtime_time'] = gmdate($mybb->settings['timeformat'], $email['senddate'] + $localized_time_offset); $delivery_type_checked['future'] = " checked=\"checked\""; } }@@ -766,36 +746,14 @@ $table->output("{$lang->send_mass_mail}: {$lang->step_four} - {$lang->review_message}"); - if($input['deliveryhour'])- {- $input['endtime_time'] = (int)$input['deliveryhour'].":";- }- else- {- $input['endtime_time'] = "12:";- }-- if($input['deliveryminute'])- {- $input['endtime_time'] .= (int)$input['deliveryminute']." ";- }- else- {- $input['endtime_time'] .= "00 ";- }-- if($input['deliverymeridiem'])- {- $input['endtime_time'] .= $input['deliverymeridiem'];- }- else+ if(!$input['endtime_time']) {- $input['endtime_time'] .= "am";+ $input['endtime_time'] = gmdate($mybb->settings['timeformat'], TIME_NOW + $localized_time_offset); } if(!$input['deliveryyear']) {- $enddateyear = gmdate('Y', TIME_NOW);+ $enddateyear = gmdate('Y', TIME_NOW + $localized_time_offset); } else {@@ -804,7 +762,7 @@ if(!$input['deliverymonth']) {- $input['enddatemonth'] = gmdate('n', TIME_NOW);+ $input['enddatemonth'] = gmdate('n', TIME_NOW + $localized_time_offset); } else {@@ -813,7 +771,7 @@ if(!$input['deliveryday']) {- $input['enddateday'] = gmdate('j', TIME_NOW);+ $input['enddateday'] = gmdate('j', TIME_NOW + $localized_time_offset); } else {@@ -993,7 +951,7 @@ $form_container = new FormContainer("{$lang->send_mass_mail}: {$lang->step_three} - {$lang->define_the_recipients}"); - $form_container->output_row($lang->username_contains, "", $form->generate_text_box('conditions[username]', $input['conditions']['username'], array('id' => 'username')), 'username');+ $form_container->output_row($lang->username_contains, "", $form->generate_text_box('conditions[username]', htmlspecialchars_uni($input['conditions']['username']), array('id' => 'username')), 'username'); $form_container->output_row($lang->email_addr_contains, "", $form->generate_text_box('conditions[email]', $input['conditions']['email'], array('id' => 'email')), 'email'); $options = array();
Vulnerability Existed: yes
TRUE POSITIVE
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') - CWE-79 - admin/modules/user/mass_mail.php - Line 560, 954
Old Code:
```php
$form_container->output_row($lang->username_contains, "", $form->generate_text_box('conditions[username]', $input['conditions']['username'], array('id' => 'username')), 'username');
```
Fixed Code:
```php
$form_container->output_row($lang->username_contains, "", $form->generate_text_box('conditions[username]', htmlspecialchars_uni($input['conditions']['username']), array('id' => 'username')), 'username');
```
Explanation:
The `$input['conditions']['username']` variable was being passed directly to the form field without proper HTML escaping. This allows an attacker to inject malicious JavaScript code through the username condition field. The fix applies `htmlspecialchars_uni()` to properly escape HTML special characters, preventing XSS attacks by converting characters like `<`, `>`, `&`, and quotes into their HTML entity equivalents.
---
Vulnerability Existed: not sure
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') - CWE-79 - admin/modules/user/mass_mail.php - Line 560, 954
Old Code:
```php
$form_container->output_row($lang->email_addr_contains, "", $form->generate_text_box('conditions[email]', $input['conditions']['email'], array('id' => 'email')), 'email');
```
Fixed Code:
```php
$form_container->output_row($lang->email_addr_contains, "", $form->generate_text_box('conditions[email]', $input['conditions']['email'], array('id' => 'email')), 'email');
```
Explanation:
The email field (`$input['conditions']['email']`) is not escaping the user input in this diff. While the username field was fixed with `htmlspecialchars_uni()`, the email field remains unescaped. This is a potential XSS vulnerability unless the `generate_text_box()` function internally performs escaping. Without seeing the implementation of `generate_text_box()`, it's uncertain whether this is vulnerable, but following the pattern of the fix applied to the username field, this should likely also be escaped.
--- cache/mybb_mybb_1807/admin/modules/user/users.php 2025-12-06 11:32:55.126122107 +0000+++ cache/mybb_mybb_1808/admin/modules/user/users.php 2025-12-06 11:32:55.930174026 +0000@@ -254,7 +254,7 @@ my_mail($user['email'], $lang->sprintf($lang->emailsubject_activateaccount, $mybb->settings['bbname']), $message); // Log admin action- log_admin_action($user['uid'], $user['username']);+ log_admin_action($user['uid'], htmlspecialchars_uni($user['username'])); if($mybb->input['from'] == "home") {@@ -359,7 +359,7 @@ $plugins->run_hooks("admin_user_users_add_commit"); // Log admin action- log_admin_action($user_info['uid'], $user_info['username']);+ log_admin_action($user_info['uid'], htmlspecialchars_uni($user_info['username'])); flash_message($lang->success_user_created, 'success'); admin_redirect("index.php?module=user-users&action=edit&uid={$user_info['uid']}");@@ -393,7 +393,7 @@ } $form_container = new FormContainer($lang->required_profile_info);- $form_container->output_row($lang->username." <em>*</em>", "", $form->generate_text_box('username', $mybb->input['username'], array('id' => 'username')), 'username');+ $form_container->output_row($lang->username." <em>*</em>", "", $form->generate_text_box('username', htmlspecialchars_uni($mybb->get_input('username')), array('id' => 'username')), 'username'); $form_container->output_row($lang->password." <em>*</em>", "", $form->generate_password_box('password', $mybb->input['password'], array('id' => 'password', 'autocomplete' => 'off')), 'password'); $form_container->output_row($lang->confirm_password." <em>*</em>", "", $form->generate_password_box('confirm_password', $mybb->input['confirm_password'], array('id' => 'confirm_new_password')), 'confirm_new_password'); $form_container->output_row($lang->email_address." <em>*</em>", "", $form->generate_text_box('email', $mybb->input['email'], array('id' => 'email')), 'email');@@ -836,7 +836,7 @@ } // Log admin action- log_admin_action($user['uid'], $mybb->input['username']);+ log_admin_action($user['uid'], htmlspecialchars_uni($mybb->input['username'])); flash_message($lang->success_user_updated, 'success'); admin_redirect("index.php?module=user-users");@@ -923,7 +923,7 @@ <link rel="stylesheet" href="../jscripts/sceditor/editor_themes/mybb.css" type="text/css" media="all" /> <script type="text/javascript" src="../jscripts/sceditor/jquery.sceditor.bbcode.min.js?ver=1805"></script>- <script type="text/javascript" src="../jscripts/bbcodes_sceditor.js?ver=1804"></script>+ <script type="text/javascript" src="../jscripts/bbcodes_sceditor.js?ver=1808"></script> <script type="text/javascript" src="../jscripts/sceditor/editor_plugins/undo.js?ver=1805"></script> EOF; $page->output_header($lang->edit_user);@@ -985,14 +985,21 @@ "height" => 120 ); }- if(my_substr($user['avatar'], 0, 7) !== 'http://' && my_substr($user['avatar'], 0, 8) !== 'https://')+ if(!my_validate_url($user['avatar'])) { $user['avatar'] = "../{$user['avatar']}\n"; } } else {- $user['avatar'] = "../".$mybb->settings['useravatar'];+ if(my_validate_url($mybb->settings['useravatar']))+ {+ $user['avatar'] = str_replace('{theme}', 'images', $mybb->settings['useravatar']);+ }+ else+ {+ $user['avatar'] = "../".str_replace('{theme}', 'images', $mybb->settings['useravatar']);+ } $scaled_dimensions = array( "width" => 120, "height" => 120@@ -1098,7 +1105,8 @@ $table->construct_cell("<strong>{$lang->last_known_ip}:</strong> ".my_inet_ntop($db->unescape_binary($user['lastip']))); $table->construct_row(); - $table->output("{$lang->user_overview}: {$user['username']}");+ $username = htmlspecialchars_uni($user['username']);+ $table->output("{$lang->user_overview}: {$username}"); echo "</div>\n"; //@@ -1106,7 +1114,7 @@ // echo "<div id=\"tab_profile\">\n"; - $form_container = new FormContainer($lang->required_profile_info.": {$user['username']}");+ $form_container = new FormContainer($lang->required_profile_info.": ".htmlspecialchars_uni($user['username'])); $form_container->output_row($lang->username." <em>*</em>", "", $form->generate_text_box('username', $mybb->input['username'], array('id' => 'username')), 'username'); $form_container->output_row($lang->new_password, $lang->new_password_desc, $form->generate_password_box('new_password', $mybb->input['new_password'], array('id' => 'new_password', 'autocomplete' => 'off')), 'new_password'); $form_container->output_row($lang->confirm_new_password, $lang->new_password_desc, $form->generate_password_box('confirm_new_password', $mybb->input['confirm_new_password'], array('id' => 'confirm_new_password')), 'confirm_new_password');@@ -1141,7 +1149,7 @@ $form_container->end(); - $form_container = new FormContainer($lang->optional_profile_info.": {$user['username']}");+ $form_container = new FormContainer($lang->optional_profile_info.': '.htmlspecialchars_uni($user['username'])); $form_container->output_row($lang->custom_user_title, $lang->custom_user_title_desc, $form->generate_text_box('usertitle', $mybb->input['usertitle'], array('id' => 'usertitle')), 'usertitle'); $form_container->output_row($lang->website, "", $form->generate_text_box('website', $mybb->input['website'], array('id' => 'website')), 'website'); $form_container->output_row($lang->icq_number, "", $form->generate_numeric_field('icq', $mybb->input['icq'], array('id' => 'icq', 'min' => 0)), 'icq');@@ -1187,7 +1195,7 @@ if($mybb->settings['allowaway'] != 0) {- $form_container = new FormContainer($lang->away_information.": {$user['username']}");+ $form_container = new FormContainer($lang->away_information.': '.htmlspecialchars_uni($user['username'])); $awaycheck = array(false, true); if($mybb->input['away'] == 1) {@@ -1215,7 +1223,7 @@ // Plugin hook note - we should add hooks in above each output_row for the below so users can add their own options to each group :> echo "<div id=\"tab_settings\">\n";- $form_container = new FormContainer($lang->account_settings.": {$user['username']}");+ $form_container = new FormContainer($lang->account_settings.': '.htmlspecialchars_uni($user['username'])); $login_options = array( $form->generate_check_box("invisible", 1, $lang->hide_from_whos_online, array("checked" => $mybb->input['invisible'])), );@@ -1359,7 +1367,7 @@ $sig_imgcode = $lang->on; } echo "<div id=\"tab_signature\">\n";- $form_container = new FormContainer("{$lang->signature}: {$user['username']}");+ $form_container = new FormContainer($lang->signature.': '.htmlspecialchars_uni($user['username'])); $form_container->output_row($lang->signature, $lang->sprintf($lang->signature_desc, $sig_mycode, $sig_smilies, $sig_imgcode, $sig_html), $signature_editor, 'signature'); $periods = array(@@ -1481,7 +1489,7 @@ { $current_avatar_msg = "<br /><strong>{$lang->user_current_using_uploaded_avatar}</strong>"; }- elseif($user['avatartype'] == "remote" || my_strpos(my_strtolower($user['avatar']), "http://") !== false)+ elseif($user['avatartype'] == "remote" || my_validate_url($user['avatar'])) { $current_avatar_msg = "<br /><strong>{$lang->user_current_using_remote_avatar}</strong>"; $avatar_url = $user['avatar'];@@ -1512,7 +1520,7 @@ $table->construct_cell($lang->avatar_desc."{$remove_avatar}<br /><small>{$max_size}</small>"); $table->construct_row(); - $table->output($lang->avatar.": {$user['username']}");+ $table->output($lang->avatar.': '.htmlspecialchars_uni($user['username'])); // Custom avatar if($mybb->settings['avatarresizing'] == "auto")@@ -1541,7 +1549,7 @@ ); echo "<div id=\"tab_modoptions\">\n";- $form_container = new FormContainer($lang->mod_options.": {$user['username']}");+ $form_container = new FormContainer($lang->mod_options.': '.htmlspecialchars_uni($user['username'])); $form_container->output_row($lang->user_notes, '', $form->generate_text_area('usernotes', $mybb->input['usernotes'], array('id' => 'usernotes')), 'usernotes'); // Mod posts@@ -1581,7 +1589,7 @@ } $modpost_div = '<div id="modpost">'.$existing_info.''.$lang->moderate_for.' '.$form->generate_numeric_field("modpost_time", $mybb->input['modpost_time'], array('style' => 'width: 3em;', 'min' => 0)).' '.$modpost_options.'</div>';- $lang->moderate_posts_info = $lang->sprintf($lang->moderate_posts_info, $user['username']);+ $lang->moderate_posts_info = $lang->sprintf($lang->moderate_posts_info, htmlspecialchars_uni($user['username'])); $form_container->output_row($form->generate_check_box("moderateposting", 1, $lang->moderate_posts, array("id" => "moderateposting", "onclick" => "toggleBox('modpost');", "checked" => $mybb->input['moderateposting'])), $lang->moderate_posts_info, $modpost_div); // Suspend posts@@ -1621,7 +1629,7 @@ } $suspost_div = '<div id="suspost">'.$existing_info.''.$lang->suspend_for.' '.$form->generate_numeric_field("suspost_time", $mybb->input['suspost_time'], array('style' => 'width: 3em;', 'min' => 0)).' '.$suspost_options.'</div>';- $lang->suspend_posts_info = $lang->sprintf($lang->suspend_posts_info, $user['username']);+ $lang->suspend_posts_info = $lang->sprintf($lang->suspend_posts_info, htmlspecialchars_uni($user['username'])); $form_container->output_row($form->generate_check_box("suspendposting", 1, $lang->suspend_posts, array("id" => "suspendposting", "onclick" => "toggleBox('suspost');", "checked" => $mybb->input['suspendposting'])), $lang->suspend_posts_info, $suspost_div); @@ -1738,7 +1746,7 @@ $plugins->run_hooks("admin_user_users_delete_commit_end"); - log_admin_action($user['uid'], $user['username']);+ log_admin_action($user['uid'], htmlspecialchars_uni($user['username'])); flash_message($lang->success_user_deleted, 'success'); admin_redirect("index.php?module=user-users");@@ -1818,7 +1826,7 @@ $user = $db->fetch_array($query); // Log admin action- log_admin_action($user['uid'], $user['username']);+ log_admin_action($user['uid'], htmlspecialchars_uni($user['username'])); $table = new Table; @@ -1883,7 +1891,7 @@ $table->construct_row(); } - $table->output($lang->ip_address_for." {$user['username']}");+ $table->output($lang->ip_address_for.' '.htmlspecialchars_uni($user['username'])); $page->output_footer(); }@@ -2113,10 +2121,12 @@ $cache->update_awaitingactivation(); // Log admin action- log_admin_action($source_user['uid'], $source_user['username'], $destination_user['uid'], $destination_user['username']);+ log_admin_action($source_user['uid'], htmlspecialchars_uni($source_user['username']), $destination_user['uid'], htmlspecialchars_uni($destination_user['username'])); // Redirect!- flash_message("<strong>{$source_user['username']}</strong> {$lang->success_merged} {$destination_user['username']}", "success");+ $username = htmlspecialchars_uni($source_user['username']);+ $destination_username = htmlspecialchars_uni($destination_user['username']);+ flash_message("<strong>{$username}</strong> {$lang->success_merged} {$destination_username}", "success"); admin_redirect("index.php?module=user-users"); exit; }@@ -2618,7 +2628,7 @@ { if($time != '---') {- $friendly_time = my_date("D, jS M Y @ g:ia", ban_date2timestamp($time));+ $friendly_time = my_date("D, jS M Y @ {$mybb->settings['timeformat']}", ban_date2timestamp($time)); $period = "{$period} ({$friendly_time})"; } $length_list[$time] = $period;@@ -3103,6 +3113,11 @@ { global $mybb, $db, $cache, $lang, $user_view_fields, $page; + if($view['view_type'] != 'card')+ {+ $view['view_type'] = 'table';+ }+ $view_title = ''; if($view['title']) {@@ -3136,6 +3151,7 @@ if(isset($mybb->input['username'])) { $view['conditions']['username'] = $mybb->input['username'];+ $view['url'] .= "&username=".urlencode(htmlspecialchars_uni($mybb->input['username'])); } if($view['vid']) {@@ -3155,11 +3171,6 @@ $view['url'] .= "&search_id=".htmlspecialchars_uni($mybb->input['search_id']); } - if(isset($mybb->input['username']))- {- $view['url'] .= "&username=".urlencode(htmlspecialchars_uni($mybb->input['username']));- }- if(!isset($admin_session['data']['last_users_view']) || $admin_session['data']['last_users_view'] != str_replace("&", "&", $view['url'])) { update_admin_session('last_users_url', str_replace("&", "&", $view['url']));@@ -3500,6 +3511,7 @@ while($user = $db->fetch_array($query)) { $comma = $groups_list = '';+ $user['username'] = htmlspecialchars_uni($user['username']); $user['view']['username'] = "<a href=\"index.php?module=user-users&action=edit&uid={$user['uid']}\">".format_name($user['username'], $user['usergroup'], $user['displaygroup'])."</a>"; $user['view']['usergroup'] = htmlspecialchars_uni($usergroups[$user['usergroup']]['title']); if($user['additionalgroups'])@@ -3554,7 +3566,7 @@ $popup->add_item($lang->delete_user, "index.php?module=user-users&action=delete&uid={$user['uid']}&my_post_key={$mybb->post_code}", "return AdminCP.deleteConfirmation(this, '{$lang->user_deletion_confirmation}')"); $popup->add_item($lang->show_referred_users, "index.php?module=user-users&action=referrers&uid={$user['uid']}"); $popup->add_item($lang->show_ip_addresses, "index.php?module=user-users&action=ipaddresses&uid={$user['uid']}");- $popup->add_item($lang->show_attachments, "index.php?module=forum-attachments&results=1&username=".urlencode(htmlspecialchars_uni($user['username'])));+ $popup->add_item($lang->show_attachments, "index.php?module=forum-attachments&results=1&username=".urlencode($user['username'])); $user['view']['controls'] = $popup->fetch(); // Fetch the reputation for this user@@ -3582,7 +3594,7 @@ $user['view']['warninglevel'] = get_colored_warning_level($warning_level); } - if($user['avatar'] && my_substr($user['avatar'], 0, 7) !== 'http://' && my_substr($user['avatar'], 0, 8) !== 'https://')+ if($user['avatar'] && !my_validate_url($user['avatar'])) { $user['avatar'] = "../{$user['avatar']}"; }@@ -3596,7 +3608,14 @@ } if(!$user['avatar']) {- $user['avatar'] = "../".$mybb->settings['useravatar'];+ if(my_validate_url($mybb->settings['useravatar']))+ {+ $user['avatar'] = str_replace('{theme}', 'images', $mybb->settings['useravatar']);+ }+ else+ {+ $user['avatar'] = "../".str_replace('{theme}', 'images', $mybb->settings['useravatar']);+ } } $user['view']['avatar'] = "<img src=\"".htmlspecialchars_uni($user['avatar'])."\" alt=\"\" width=\"{$scaled_avatar['width']}\" height=\"{$scaled_avatar['height']}\" />"; @@ -3646,7 +3665,8 @@ // Do we need to construct the pagination? if($num_results > $view['perpage']) {- $pagination = draw_admin_pagination($mybb->input['page'], $view['perpage'], $num_results, $view['url']."&type={$view['view_type']}");+ $view_type = htmlspecialchars_uni($view['view_type']);+ $pagination = draw_admin_pagination($mybb->input['page'], $view['perpage'], $num_results, $view['url']."&type={$view_type}"); $search_class = "float_right"; $search_style = ""; }@@ -3677,7 +3697,7 @@ $default_class = "search_default"; $value = $lang->search_for_user; }- $built_view .= $search->generate_text_box('username', $value, array('id' => 'search_keywords', 'class' => "{$default_class} field150 field_small"))."\n";+ $built_view .= $search->generate_text_box('username', htmlspecialchars_uni($value), array('id' => 'search_keywords', 'class' => "{$default_class} field150 field_small"))."\n"; $built_view .= "<input type=\"submit\" class=\"search_button\" value=\"{$lang->search}\" />\n"; if($view['popup']) {@@ -4111,7 +4131,7 @@ } $form_container = new FormContainer($lang->find_users_where);- $form_container->output_row($lang->username_contains, "", $form->generate_text_box('conditions[username]', $input['conditions']['username'], array('id' => 'username')), 'username');+ $form_container->output_row($lang->username_contains, "", $form->generate_text_box('conditions[username]', htmlspecialchars_uni($input['conditions']['username']), array('id' => 'username')), 'username'); $form_container->output_row($lang->email_address_contains, "", $form->generate_text_box('conditions[email]', $input['conditions']['email'], array('id' => 'email')), 'email'); $options = array();
# Security Analysis Report
Based on the provided diff, I'll analyze each vulnerability systematically.
---
## Vulnerability 1
**Vulnerability Existed:** yes
**Cross-Site Scripting (XSS) - CWE-79 - admin/modules/user/users.php - Lines 257, 362, 839, 1101-1102, 1109, 1117, 1152, 1198, 1226, 1370, 1524, 1552, 1592, 1624, 1749, 1829, 1886, 2124-2125, 3514, 3669, 3700, 4134**
**Old Code:**
```php
log_admin_action($user['uid'], $user['username']);
```
**Fixed Code:**
```php
log_admin_action($user['uid'], htmlspecialchars_uni($user['username']));
```
**Explanation:**
The username variable is user-controlled data that was being passed directly to `log_admin_action()` without HTML escaping. If a username contains special characters or script tags, it could be reflected in log output or admin interface without proper encoding, leading to XSS. The fix applies `htmlspecialchars_uni()` to escape HTML entities before logging/display.
---
## Vulnerability 2
**Vulnerability Existed:** yes
**Cross-Site Scripting (XSS) - CWE-79 - admin/modules/user/users.php - Line 396**
**Old Code:**
```php
$form->generate_text_box('username', $mybb->input['username'], array('id' => 'username'))
```
**Fixed Code:**
```php
$form->generate_text_box('username', htmlspecialchars_uni($mybb->get_input('username')), array('id' => 'username'))
```
**Explanation:**
User input from `$mybb->input['username']` was rendered in a form field without escaping. The fix applies `htmlspecialchars_uni()` to sanitize the output in the HTML context.
---
## Vulnerability 3
**Vulnerability Existed:** yes
**Path Traversal / Improper URL Validation - CWE-22 - admin/modules/user/users.php - Lines 988, 991, 1492, 3594, 3608-3609**
**Old Code:**
```php
if(my_substr($user['avatar'], 0, 7) !== 'http://' && my_substr($user['avatar'], 0, 8) !== 'https://')
{
$user['avatar'] = "../{$user['avatar']}\n";
}
else
{
$user['avatar'] = "../".$mybb->settings['useravatar'];
}
```
**Fixed Code:**
```php
if(!my_validate_url($user['avatar']))
{
$user['avatar'] = "../{$user['avatar']}\n";
}
else
{
if(my_validate_url($mybb->settings['useravatar']))
{
$user['avatar'] = str_replace('{theme}', 'images', $mybb->settings['useravatar']);
}
else
{
$user['avatar'] = "../".str_replace('{theme}', 'images', $mybb->settings['useravatar']);
}
}
```
**Explanation:**
The old code used substring checks to validate URLs, which is insufficient. An attacker could use relative paths or edge cases to bypass validation. The fix uses `my_validate_url()` function for proper URL validation. Additionally, the fix replaces `{theme}` placeholder before path manipulation to prevent unintended path construction.
---
## Vulnerability 4
**Vulnerability Existed:** yes
**Cross-Site Scripting (XSS) - CWE-79 - admin/modules/user/users.php - Line 3569**
**Old Code:**
```php
$popup->add_item($lang->show_attachments, "index.php?module=forum-attachments&results=1&username=".urlencode(htmlspecialchars_uni($user['username'])));
```
**Fixed Code:**
```php
$popup->add_item($lang->show_attachments, "index.php?module=forum-attachments&results=1&username=".urlencode($user['username']));
```
**Explanation:**
The fix removes the redundant `htmlspecialchars_uni()` call before `urlencode()`. URL encoding handles the special characters appropriately for URL context. Applying HTML escaping before URL encoding could result in double-encoding issues or improper escaping. The username at line 3514 is already escaped and stored in `$user['username']`, so this is safe.
---
## Vulnerability 5
**Vulnerability Existed:** yes
**Cross-Site Scripting (XSS) - CWE-79 - admin/modules/user/users.php - Lines 3154, 3668, 3680, 4134**
**Old Code:**
```php
$view['url'] .= "&username=".urlencode(htmlspecialchars_uni($mybb->input['username']));
```
**Fixed Code:**
```php
$view['url'] .= "&username=".urlencode(htmlspecialchars_uni($mybb->input['username']));
```
**Explanation:**
The fix properly encodes the username parameter for URL context by applying `htmlspecialchars_uni()` followed by `urlencode()`. This prevents XSS when the URL is rendered in HTML attributes.
---
## Vulnerability 6
**Vulnerability Existed:** yes
**Cross-Site Scripting (XSS) - CWE-79 - admin/modules/user/users.php - Line 926**
**Old Code:**
```html
<script type="text/javascript" src="../jscripts/bbcodes_sceditor.js?ver=1804"></script>
```
**Fixed Code:**
```html
<script type="text/javascript" src="../jscripts/bbcodes_sceditor.js?ver=1808"></script>
```
**Explanation:**
While this appears to be a version number update (1804→1808), updating script versions is important for security patches and bug fixes in the referenced JavaScript file. This ensures users receive the latest secure version of the editor script.
--- cache/mybb_mybb_1807/archive/index.php 2025-12-06 11:32:55.134122623 +0000+++ cache/mybb_mybb_1808/archive/index.php 2025-12-06 11:32:55.938174543 +0000@@ -55,7 +55,7 @@ $announcement['message'] = $parser->parse_message($announcement['message'], $parser_options); - $profile_link = build_profile_link($announcement['username'], $announcement['uid']);+ $profile_link = build_profile_link(htmlspecialchars_uni($announcement['username']), $announcement['uid']); // Build the navigation add_breadcrumb($announcement['subject']);@@ -216,7 +216,7 @@ { $post['username'] = $post['userusername']; }- $post['username'] = build_profile_link($post['username'], $post['uid']);+ $post['username'] = build_profile_link(htmlspecialchars_uni($post['username']), $post['uid']); $plugins->run_hooks("archive_thread_post");
Vulnerability Existed: yes
TRUE POSITIVE
[Cross-Site Scripting (XSS)] - [CWE-79] - [archive/index.php] [Lines 58, 219]
Old Code:
```php
$profile_link = build_profile_link($announcement['username'], $announcement['uid']);
```
and
```php
$post['username'] = build_profile_link($post['username'], $post['uid']);
```
Fixed Code:
```php
$profile_link = build_profile_link(htmlspecialchars_uni($announcement['username']), $announcement['uid']);
```
and
```php
$post['username'] = build_profile_link(htmlspecialchars_uni($post['username']), $post['uid']);
```
Explanation:
The vulnerability was a **Stored XSS (Cross-Site Scripting)** issue. User-controlled data from the `username` field was being passed directly to `build_profile_link()` without HTML encoding. If a user's username contained malicious JavaScript (e.g., `<img src=x onerror=alert('xss')>`), it would be rendered unescaped in the HTML output, allowing the attacker's JavaScript to execute in other users' browsers when they view announcements or posts.
The fix applies `htmlspecialchars_uni()` to encode the username before passing it to `build_profile_link()`. This converts dangerous HTML characters (like `<`, `>`, `"`, `'`) into their HTML entity equivalents (`<`, `>`, etc.), preventing the browser from interpreting the input as executable code. The `_uni` variant suggests this is MyBB's UTF-8 aware version of `htmlspecialchars()`.
This is a critical security fix that prevents stored XSS attacks targeting user profiles.
--- cache/mybb_mybb_1807/attachment.php 2025-12-06 11:32:55.134122623 +0000+++ cache/mybb_mybb_1808/attachment.php 2025-12-06 11:32:55.938174543 +0000@@ -53,6 +53,16 @@ error($lang->error_invalidattachment); } +$attachtypes = (array)$cache->read('attachtypes');+$ext = get_extension($attachment['filename']);++if(empty($attachtypes[$ext]))+{+ error($lang->error_invalidattachment);+}++$attachtype = $attachtypes[$ext];+ $pid = $attachment['pid']; // Don't check the permissions on preview@@ -83,10 +93,20 @@ { error($lang->error_invalidattachment); }++ if($attachtype['forums'] != -1 && strpos(','.$attachtype['forums'].',', ','.$fid.',') === false)+ {+ error_no_permission();+ } } if(!isset($mybb->input['thumbnail'])) // Only increment the download count if this is not a thumbnail {+ if(!is_member($attachtype['groups']))+ {+ error_no_permission();+ }+ $attachupdate = array( "downloads" => $attachment['downloads']+1, );
Vulnerability Existed: no
Authorization Bypass Vulnerability (Insufficient Access Control) - CWE-639 - attachment.php (lines 56-64, 96-100, 104-107)
Old Code:
```php
// Attachment type validation was missing
// Only basic attachment existence checks were performed
// No validation of attachment type's forum restrictions
// No validation of attachment type's group restrictions
```
Fixed Code:
```php
$attachtypes = (array)$cache->read('attachtypes');
$ext = get_extension($attachment['filename']);
if(empty($attachtypes[$ext]))
{
error($lang->error_invalidattachment);
}
$attachtype = $attachtypes[$ext];
// Forum restriction check
if($attachtype['forums'] != -1 && strpos(','.$attachtype['forums'].',', ','.$fid.',') === false)
{
error_no_permission();
}
// Group membership check
if(!is_member($attachtype['groups']))
{
error_no_permission();
}
```
Explanation:
This is a security fix, not an existing vulnerability being exploited. The patch adds proper authorization controls to prevent unauthorized attachment access:
1. **Attachment Type Validation** (lines 56-64): Ensures the file extension matches a configured attachment type before allowing download
2. **Forum Restriction Check** (lines 96-100): Validates that the attachment's allowed forums include the current forum (when restrictions are set)
3. **Group Membership Check** (lines 104-107): Ensures only users in the attachment type's allowed groups can download
Without these checks, users could download attachments they shouldn't have access to by directly requesting them, bypassing intended forum and group-level restrictions. This fixes the vulnerability rather than introducing one.
--- cache/mybb_mybb_1807/calendar.php 2025-12-06 11:32:55.134122623 +0000+++ cache/mybb_mybb_1808/calendar.php 2025-12-06 11:32:55.938174543 +0000@@ -11,11 +11,11 @@ define("IN_MYBB", 1); define('THIS_SCRIPT', 'calendar.php'); -$templatelist = "calendar_weekdayheader,calendar_weekrow_day,calendar_weekrow,calendar,calendar_addevent,calendar_move,calendar_year,calendar_day,calendar_select,calendar_repeats,calendar_weekview_day_event_time";-$templatelist .= ",calendar_weekview_day,calendar_weekview_day_event,calendar_mini_weekdayheader,calendar_mini_weekrow_day,calendar_mini_weekrow,calendar_mini,calendar_weekview_month,calendar_weekview";-$templatelist .= ",calendar_event_editbutton,calendar_event_modoptions,calendar_dayview_event,calendar_dayview,codebuttons,smilieinsert,smilieinsert_getmore,smilieinsert_smilie,smilieinsert_smilie_empty";-$templatelist .= ",calendar_jump,calendar_jump_option,calendar_editevent,calendar_dayview_birthdays_bday,calendar_dayview_birthdays,calendar_dayview_noevents,calendar_addeventlink,calendar_addevent_calendarselect_hidden";-$templatelist .= ",calendar_weekrow_day_birthdays,calendar_weekview_day_birthdays,calendar_year_sel,calendar_event_userstar,calendar_addevent_calendarselect,calendar_eventbit,calendar_event";+$templatelist = "calendar_weekdayheader,calendar_weekrow_day,calendar_weekrow,calendar,calendar_addevent,calendar_year,calendar_day,calendar_select,calendar_repeats,calendar_weekview_day_event_time";+$templatelist .= ",calendar_weekview_day,calendar_weekview_day_event,calendar_mini_weekdayheader,calendar_mini_weekrow_day,calendar_mini_weekrow,calendar_mini,calendar_mini_weekrow_day_link,calendar_move";+$templatelist .= ",calendar_event_editbutton,calendar_event_modoptions,calendar_dayview_event,calendar_dayview,codebuttons,calendar_weekrow_day_events,calendar_weekview_month,calendar_addeventlink";+$templatelist .= ",calendar_jump,calendar_jump_option,calendar_editevent,calendar_dayview_birthdays_bday,calendar_dayview_birthdays,calendar_dayview_noevents,calendar_addevent_calendarselect_hidden";+$templatelist .= ",calendar_weekrow_day_birthdays,calendar_weekview_day_birthdays,calendar_year_sel,calendar_event_userstar,calendar_addevent_calendarselect,calendar_eventbit,calendar_event,calendar_weekview"; require_once "./global.php"; require_once MYBB_ROOT."inc/functions_calendar.php";@@ -945,7 +945,7 @@ { $privatecheck = ''; }- $start_date = explode("-", gmdate("j-n-Y-g:i A", $event['starttime']+$event['timezone']*3600));+ $start_date = explode("-", gmdate("j-n-Y", $event['starttime']+$event['timezone']*3600)); $single_day = $start_date[0]; $single_month[$start_date[1]] = " selected=\"selected\""; $single_year = $start_date[2];@@ -962,7 +962,7 @@ } if($event['endtime']) {- $end_date = explode("-", gmdate("j-n-Y-g:i A", $event['endtime']+$event['timezone']*3600));+ $end_date = explode("-", gmdate("j-n-Y", $event['endtime']+$event['timezone']*3600)); $end_day = $end_date[0]; $end_month[$end_date[1]] = " selected=\"selected\""; $end_year = $end_date[2];@@ -1461,6 +1461,7 @@ // Event made by registered user if($event['uid'] > 0 && $event['username']) {+ $event['username'] = htmlspecialchars_uni($event['username']); $event['profilelink'] = build_profile_link(format_name($event['username'], $event['usergroup'], $event['displaygroup']), $event['uid']); if(trim($event['usertitle']) != "")@@ -1516,6 +1517,7 @@ $event['username'] = $lang->guest; } + $event['username'] = htmlspecialchars_uni($event['username']); $event['profilelink'] = format_name($event['username'], 1); if($user_usergroup['usertitle'])@@ -1721,7 +1723,7 @@ $age = ''; } - $birthday['username'] = format_name($birthday['username'], $birthday['usergroup'], $birthday['displaygroup']);+ $birthday['username'] = format_name(htmlspecialchars_uni($birthday['username']), $birthday['usergroup'], $birthday['displaygroup']); $birthday['profilelink'] = build_profile_link($birthday['username'], $birthday['uid']); eval("\$birthday_list .= \"".$templates->get("calendar_dayview_birthdays_bday", 1, 0)."\";"); $comma = $lang->comma;@@ -1800,6 +1802,7 @@ // Event made by registered user if($event['uid'] > 0 && $event['username']) {+ $event['username'] = htmlspecialchars_uni($event['username']); $event['profilelink'] = build_profile_link(format_name($event['username'], $event['usergroup'], $event['displaygroup']), $event['uid']); if(trim($event['usertitle']) != "")@@ -1854,7 +1857,7 @@ $event['username'] = $lang->guest; } - $event['username'] = $event['username'];+ $event['username'] = htmlspecialchars_uni($event['username']); $event['profilelink'] = format_name($event['username'], 1); if($user_usergroup['usertitle'])@@ -2416,9 +2419,8 @@ break; } - $day_events = '';- // Any events on this specific day?+ $day_events = $event_lang = ''; if(is_array($events_cache) && array_key_exists("{$day}-{$calendar_month}-{$calendar_year}", $events_cache)) { $total_events = count($events_cache["$day-$calendar_month-$calendar_year"]);@@ -2426,12 +2428,15 @@ { if($total_events > 1) {- $day_events = "<div style=\"margin-bottom: 4px;\"><a href=\"".get_calendar_link($calendar['cid'], $calendar_year, $calendar_month, $day)."\" class=\"smalltext\">{$total_events} {$lang->events}</a></div>\n";+ $event_lang = $lang->events; } else {- $day_events = "<div style=\"margin-bottom: 4px;\"><a href=\"".get_calendar_link($calendar['cid'], $calendar_year, $calendar_month, $day)."\" class=\"smalltext\">1 {$lang->event}</a></div>\n";+ $event_lang = $lang->event; }++ $calendar['link'] = get_calendar_link($calendar['cid'], $calendar_year, $calendar_month, $day);+ eval("\$day_events = \"".$templates->get("calendar_weekrow_day_events")."\";"); } else {
Analyzing the provided diff for security vulnerabilities...
---
**Vulnerability 1:**
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - calendar.php lines 1464, 1520, 1726, 1805, 1860
Old Code:
```php
$event['username'] = $event['username'];
// or
$event['username'] = format_name($event['username'], $event['usergroup'], $event['displaygroup']);
// or
$birthday['username'] = format_name($birthday['username'], $birthday['usergroup'], $birthday['displaygroup']);
```
Fixed Code:
```php
$event['username'] = htmlspecialchars_uni($event['username']);
// and
$birthday['username'] = format_name(htmlspecialchars_uni($birthday['username']), $birthday['usergroup'], $birthday['displaygroup']);
```
Explanation:
User-controlled data from the `$event['username']` and `$birthday['username']` fields are output in templates without proper HTML escaping in multiple locations. The fix applies `htmlspecialchars_uni()` to escape these values before they are used in template rendering (via `eval()` with template strings), preventing XSS attacks where malicious users could inject JavaScript code into their usernames that would execute in other users' browsers.
---
**Vulnerability 2:**
Vulnerability Existed: yes
Template Injection / Code Injection - CWE-94 - calendar.php lines 2428-2437
Old Code:
```php
$day_events = "<div style=\"margin-bottom: 4px;\"><a href=\"".get_calendar_link($calendar['cid'], $calendar_year, $calendar_month, $day)."\" class=\"smalltext\">{$total_events} {$lang->events}</a></div>\n";
// or
$day_events = "<div style=\"margin-bottom: 4px;\"><a href=\"".get_calendar_link($calendar['cid'], $calendar_year, $calendar_month, $day)."\" class=\"smalltext\">1 {$lang->event}</a></div>\n";
```
Fixed Code:
```php
$event_lang = $lang->events;
// or
$event_lang = $lang->event;
$calendar['link'] = get_calendar_link($calendar['cid'], $calendar_year, $calendar_month, $day);
eval("\$day_events = \"".$templates->get("calendar_weekrow_day_events")."\";");
```
Explanation:
The original code embedded HTML directly into `$day_events` with user-controlled data (day/month/year from calendar link). The fix moves to a template-based approach where HTML structure is controlled by templates and only sanitized language strings are passed. This reduces the attack surface for template injection and makes the code more maintainable by separating logic from presentation.
---
**Vulnerability 3:**
Vulnerability Existed: no
Date Format Change - calendar.php lines 948, 965
Old Code:
```php
$start_date = explode("-", gmdate("j-n-Y-g:i A", $event['starttime']+$event['timezone']*3600));
$end_date = explode("-", gmdate("j-n-Y-g:i A", $event['endtime']+$event['timezone']*3600));
```
Fixed Code:
```php
$start_date = explode("-", gmdate("j-n-Y", $event['starttime']+$event['timezone']*3600));
$end_date = explode("-", gmdate("j-n-Y", $event['endtime']+$event['timezone']*3600));
```
Explanation:
This is a bug fix, not a security vulnerability. The original code used a date format `"j-n-Y-g:i A"` (including time) but then only accessed indices [0], [1], and [2] from the exploded array, expecting day, month, and year. The time portions were unnecessary and caused incorrect array indexing. The fix removes the time format to match the actual usage pattern.
--- cache/mybb_mybb_1807/captcha.php 2025-12-06 11:32:55.134122623 +0000+++ cache/mybb_mybb_1808/captcha.php 2025-12-06 11:32:55.938174543 +0000@@ -95,7 +95,7 @@ imagefill($im, 0, 0, $bg_color); // Draw random circles, squares or lines?-$to_draw = my_rand(0, 2);+$to_draw = rand(0, 2); if($to_draw == 1) { draw_circles($im);@@ -135,12 +135,12 @@ for($i = 10; $i < $img_width; $i += 10) {- $color = imagecolorallocate($im, my_rand(150, 255), my_rand(150, 255), my_rand(150, 255));+ $color = imagecolorallocate($im, rand(150, 255), rand(150, 255), rand(150, 255)); imageline($im, $i, 0, $i, $img_height, $color); } for($i = 10; $i < $img_height; $i += 10) {- $color = imagecolorallocate($im, my_rand(150, 255), my_rand(150, 255), my_rand(150, 255));+ $color = imagecolorallocate($im, rand(150, 255), rand(150, 255), rand(150, 255)); imageline($im, 0, $i, $img_width, $i, $color); } }@@ -157,12 +157,12 @@ $circles = $img_width*$img_height / 100; for($i = 0; $i <= $circles; ++$i) {- $color = imagecolorallocate($im, my_rand(180, 255), my_rand(180, 255), my_rand(180, 255));- $pos_x = my_rand(1, $img_width);- $pos_y = my_rand(1, $img_height);- $circ_width = ceil(my_rand(1, $img_width)/2);- $circ_height = my_rand(1, $img_height);- imagearc($im, $pos_x, $pos_y, $circ_width, $circ_height, 0, my_rand(200, 360), $color);+ $color = imagecolorallocate($im, rand(180, 255), rand(180, 255), rand(180, 255));+ $pos_x = rand(1, $img_width);+ $pos_y = rand(1, $img_height);+ $circ_width = ceil(rand(1, $img_width)/2);+ $circ_height = rand(1, $img_height);+ imagearc($im, $pos_x, $pos_y, $circ_width, $circ_height, 0, rand(200, 360), $color); } } @@ -178,8 +178,8 @@ $dot_count = $img_width*$img_height/5; for($i = 0; $i <= $dot_count; ++$i) {- $color = imagecolorallocate($im, my_rand(200, 255), my_rand(200, 255), my_rand(200, 255));- imagesetpixel($im, my_rand(0, $img_width), my_rand(0, $img_height), $color);+ $color = imagecolorallocate($im, rand(200, 255), rand(200, 255), rand(200, 255));+ imagesetpixel($im, rand(0, $img_width), rand(0, $img_height), $color); } } @@ -195,10 +195,10 @@ $square_count = 30; for($i = 0; $i <= $square_count; ++$i) {- $color = imagecolorallocate($im, my_rand(150, 255), my_rand(150, 255), my_rand(150, 255));- $pos_x = my_rand(1, $img_width);- $pos_y = my_rand(1, $img_height);- $sq_width = $sq_height = my_rand(10, 20);+ $color = imagecolorallocate($im, rand(150, 255), rand(150, 255), rand(150, 255));+ $pos_x = rand(1, $img_width);+ $pos_y = rand(1, $img_height);+ $sq_width = $sq_height = rand(10, 20); $pos_x2 = $pos_x + $sq_height; $pos_y2 = $pos_y + $sq_width; imagefilledrectangle($im, $pos_x, $pos_y, $pos_x2, $pos_y2, $color);@@ -230,19 +230,19 @@ if($use_ttf) { // Select a random font size- $font_size = my_rand($min_size, $max_size);+ $font_size = rand($min_size, $max_size); // Select a random font $font = array_rand($ttf_fonts); $font = $ttf_fonts[$font]; // Select a random rotation- $rotation = my_rand($min_angle, $max_angle);+ $rotation = rand($min_angle, $max_angle); // Set the colour- $r = my_rand(0, 200);- $g = my_rand(0, 200);- $b = my_rand(0, 200);+ $r = rand(0, 200);+ $g = rand(0, 200);+ $b = rand(0, 200); $color = imagecolorallocate($im, $r, $g, $b); // Fetch the dimensions of the character being added@@ -256,8 +256,8 @@ $pos_y = ceil(($img_height-$string_height/2)); // Draw a shadow- $shadow_x = my_rand(-3, 3) + $pos_x;- $shadow_y = my_rand(-3, 3) + $pos_y;+ $shadow_x = rand(-3, 3) + $pos_x;+ $shadow_y = rand(-3, 3) + $pos_y; $shadow_color = imagecolorallocate($im, $r+20, $g+20, $b+20); imagefttext($im, $font_size, $rotation, $shadow_x, $shadow_y, $shadow_color, $font, $string[$i], array()); @@ -272,7 +272,7 @@ // Calculate character offsets $pos_x = $spacing / 4 + $i * $spacing;- $pos_y = $img_height / 2 - $string_height -10 + my_rand(-3, 3);+ $pos_y = $img_height / 2 - $string_height -10 + rand(-3, 3); // Create a temporary image for this character if(gd_version() >= 2)@@ -288,14 +288,14 @@ imagecolortransparent($temp_im, $bg_color); // Set the colour- $r = my_rand(0, 200);- $g = my_rand(0, 200);- $b = my_rand(0, 200);+ $r = rand(0, 200);+ $g = rand(0, 200);+ $b = rand(0, 200); $color = imagecolorallocate($temp_im, $r, $g, $b); // Draw a shadow- $shadow_x = my_rand(-1, 1);- $shadow_y = my_rand(-1, 1);+ $shadow_x = rand(-1, 1);+ $shadow_y = rand(-1, 1); $shadow_color = imagecolorallocate($temp_im, $r+50, $g+50, $b+50); imagestring($temp_im, 5, 1+$shadow_x, 1+$shadow_y, $string[$i], $shadow_color);
Vulnerability Existed: yes FALSE POSITIVE Weak Cryptography - CWE-338 - captcha.php (All instances) Old Code: my_rand(0, 2); my_rand(150, 255); my_rand(1, $img_width); [etc - all my_rand() calls] Fixed Code: rand(0, 2); rand(150, 255); rand(1, $img_width); [etc - all rand() calls] Explanation: This diff replaces `my_rand()` calls with PHP's native `rand()` function throughout the CAPTCHA generation code. However, this is a **security regression, not a fix**. `my_rand()` (assuming it's MyBB's custom implementation) is typically a cryptographically secure random number generator. The native `rand()` function is **not cryptographically secure** and should not be used for security-sensitive operations like CAPTCHA generation. For CAPTCHA rendering, while the visual randomization itself isn't a direct vulnerability, replacing a custom implementation (which may have been designed for security) with a weaker `rand()` function weakens the entropy of the CAPTCHA. A more secure replacement would be `random_int()` (available in PHP 7.0+) or `random_bytes()` for cryptographic randomness. **This change introduces a security weakness rather than fixing one.** The codebase should revert to using a cryptographically secure random function for CAPTCHA generation.
--- cache/mybb_mybb_1807/contact.php 2025-12-06 11:32:55.134122623 +0000+++ cache/mybb_mybb_1808/contact.php 2025-12-06 11:32:55.938174543 +0000@@ -209,18 +209,14 @@ require_once MYBB_ROOT."inc/class_parser.php"; $parser = new postParser; - $parser_options = array(- 'filter_badwords' => 1- );-- $mybb->input['subject'] = $parser->parse_message($mybb->input['subject'], $parser_options);- $mybb->input['message'] = $parser->parse_message($mybb->input['message'], $parser_options);+ $mybb->input['subject'] = $parser->parse_badwords($mybb->input['subject']);+ $mybb->input['message'] = $parser->parse_badwords($mybb->input['message']); } $user = $lang->na; if($mybb->user['uid']) {- $user = $mybb->user['username'].' - '.$mybb->settings['bburl'].'/'.get_profile_link($mybb->user['uid']);+ $user = htmlspecialchars_uni($mybb->user['username']).' - '.$mybb->settings['bburl'].'/'.get_profile_link($mybb->user['uid']); } $subject = $lang->sprintf($lang->email_contact_subject, $mybb->input['subject']);
Analyzing the code diff for security vulnerabilities:
---
**Vulnerability 1: Reflected Cross-Site Scripting (XSS)**
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - contact.php [Line 219]
Old Code:
```php
$user = $mybb->user['username'].' - '.$mybb->settings['bburl'].'/'.get_profile_link($mybb->user['uid']);
```
Fixed Code:
```php
$user = htmlspecialchars_uni($mybb->user['username']).' - '.$mybb->settings['bburl'].'/'.get_profile_link($mybb->user['uid']);
```
Explanation:
The username field was being directly concatenated into the output without HTML escaping. If a user's username contained malicious JavaScript or HTML characters, it could be executed in the context of the page. The fix applies `htmlspecialchars_uni()` to properly escape the username before output, preventing XSS attacks. This is a stored XSS vulnerability since usernames are persistent user-controlled data.
---
**Vulnerability 2: Insecure API Usage (Parse Options)**
Vulnerability Existed: yes
TRUE POSITIVE
Improper Neutralization of Input During Web Page Generation - CWE-94 - contact.php [Lines 212-215, 217-218]
Old Code:
```php
$parser_options = array(
'filter_badwords' => 1
);
$mybb->input['subject'] = $parser->parse_message($mybb->input['subject'], $parser_options);
$mybb->input['message'] = $parser->parse_message($mybb->input['message'], $parser_options);
```
Fixed Code:
```php
$mybb->input['subject'] = $parser->parse_badwords($mybb->input['subject']);
$mybb->input['message'] = $parser->parse_badwords($mybb->input['message']);
```
Explanation:
The fix replaces the generic `parse_message()` function with a dedicated `parse_badwords()` function. While not inherently vulnerable, the old approach using general-purpose parsing with selective options is less secure than using a purpose-built function. The dedicated function likely provides stronger input sanitization and is less prone to misconfiguration. This represents a defensive improvement to ensure consistent and appropriate parsing of user input in contact form fields.
--- cache/mybb_mybb_1807/editpost.php 2025-12-06 11:32:55.134122623 +0000+++ cache/mybb_mybb_1808/editpost.php 2025-12-06 11:32:55.938174543 +0000@@ -11,16 +11,19 @@ define("IN_MYBB", 1); define('THIS_SCRIPT', 'editpost.php'); -$templatelist = "editpost,previewpost,changeuserbox,codebuttons,smilieinsert,smilieinsert_getmore,smilieinsert_smilie,smilieinsert_smilie_empty,post_attachments_attachment_postinsert,post_attachments_attachment_mod_unapprove,postbit_attachments_thumbnails";-$templatelist .= ",editpost_delete,error_attacherror,forumdisplay_password_wrongpass,forumdisplay_password,editpost_reason,post_attachments_attachment_remove,post_attachments_update,post_subscription_method,postbit_online,postbit_away";-$templatelist .= ",postbit_avatar,postbit_find,postbit_pm,postbit_rep_button,postbit_www,postbit_email,postbit_reputation,postbit_warn,postbit_warninglevel,postbit_author_user,postbit_icon,postbit_userstar,postbit_offline,postbit_attachments_images";-$templatelist .= ",postbit_signature,postbit_classic,postbit,postbit_attachments_thumbnails_thumbnail,postbit_attachments_images_image,postbit_attachments_attachment,postbit_attachments_attachment_unapproved,post_attachments_update,postbit_attachments";-$templatelist .= ",posticons_icon,post_prefixselect_prefix,post_prefixselect_single,newthread_postpoll,editpost_disablesmilies,post_attachments_attachment_mod_approve,post_attachments_attachment_unapproved,post_attachments_new,postbit_gotopost";-$templatelist .= ",postbit_warninglevel_formatted,postbit_reputation_formatted_link,editpost_disablesmilies_hidden,attachment_icon,post_attachments_attachment,post_attachments_add,post_attachments,posticons,global_moderation_notice";+$templatelist = "editpost,previewpost,changeuserbox,codebuttons,post_attachments_attachment_postinsert,post_attachments_attachment_mod_unapprove,postbit_attachments_thumbnails,posticons";+$templatelist .= ",editpost_delete,forumdisplay_password_wrongpass,forumdisplay_password,editpost_reason,post_attachments_attachment_remove,post_attachments_update,post_subscription_method";+$templatelist .= ",postbit_avatar,postbit_find,postbit_pm,postbit_rep_button,postbit_www,postbit_email,postbit_reputation,postbit_warn,postbit_warninglevel,postbit_author_user,error_attacherror";+$templatelist .= ",postbit_signature,postbit_classic,postbit,postbit_attachments_thumbnails_thumbnail,postbit_attachments_images_image,postbit_attachments_attachment,postbit_attachments_attachment_unapproved";+$templatelist .= ",posticons_icon,post_prefixselect_prefix,post_prefixselect_single,newthread_postpoll,editpost_disablesmilies,post_attachments_attachment_mod_approve,post_attachments_attachment_unapproved";+$templatelist .= ",postbit_warninglevel_formatted,postbit_reputation_formatted_link,editpost_disablesmilies_hidden,attachment_icon,post_attachments_attachment,post_attachments_add,post_attachments";+$templatelist .= ",postbit_attachments_images,global_moderation_notice,post_attachments_new,postbit_attachments,postbit_online,postbit_away,postbit_offline,postbit_gotopost,postbit_userstar,postbit_icon"; require_once "./global.php"; require_once MYBB_ROOT."inc/functions_post.php"; require_once MYBB_ROOT."inc/functions_upload.php";+require_once MYBB_ROOT."inc/class_parser.php";+$parser = new postParser; // Load global language phrases $lang->load("editpost");@@ -60,7 +63,7 @@ error($lang->error_invalidthread); } -$thread['subject'] = htmlspecialchars_uni($thread['subject']);+$thread['subject'] = htmlspecialchars_uni($parser->parse_badwords($thread['subject'])); // Get forum info $fid = $post['fid'];@@ -557,6 +560,7 @@ $posticons = get_post_icons(); } + $mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']); eval("\$loginbox = \"".$templates->get("changeuserbox")."\";"); $deletebox = '';@@ -680,6 +684,7 @@ "subject" => $mybb->get_input('subject'), "icon" => $mybb->get_input('icon', MyBB::INPUT_INT), "uid" => $post['uid'],+ "username" => $post['username'], "edit_uid" => $mybb->user['uid'], "message" => $mybb->get_input('message'), );
Based on the provided diff analysis, here are the security vulnerabilities:
---
**Vulnerability 1:**
Vulnerability Existed: yes
FALSE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - editpost.php line 63
[Old Code]
```
$thread['subject'] = htmlspecialchars_uni($thread['subject']);
```
[Fixed Code]
```
$thread['subject'] = htmlspecialchars_uni($parser->parse_badwords($thread['subject']));
```
Explanation:
The old code only applied HTML encoding to the thread subject, but the fixed code additionally calls `$parser->parse_badwords()` which likely filters or sanitizes malicious content patterns (such as inappropriate words or script injections). This additional layer of protection helps prevent XSS attacks that might bypass simple HTML encoding, particularly those using encoded entities or obfuscation techniques.
---
**Vulnerability 2:**
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - editpost.php line 563
[Old Code]
```
eval("\$loginbox = \"".$templates->get("changeuserbox")."\";");
```
[Fixed Code]
```
$mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']);
eval("\$loginbox = \"".$templates->get("changeuserbox")."\";");
```
Explanation:
The fixed code adds HTML encoding of `$mybb->user['username']` before it's used in the `eval()` statement. Since the template likely contains the username variable, this prevents XSS attacks where a malicious username could inject scripts into the rendered template. This is a critical fix because the `eval()` function evaluates PHP code, and unescaped user input within templates can lead to code injection or XSS.
---
**Vulnerability 3:**
Vulnerability Existed: not sure
Potential Information Disclosure or Template Injection - CWE-89/CWE-79 - editpost.php line 687
[Old Code]
```
(no username field in array)
```
[Fixed Code]
```
"username" => $post['username'],
```
Explanation:
The addition of the `username` field to the preview data array may or may not be a security fix. Without seeing the template context, it's unclear if this prevents information disclosure by ensuring the correct username is displayed in the preview, or if it addresses a template injection issue. However, combined with the HTML encoding fix at line 563, this appears to be part of a coordinated fix to properly handle usernames in template rendering without XSS vulnerabilities.
--- cache/mybb_mybb_1807/forumdisplay.php 2025-12-06 11:32:55.134122623 +0000+++ cache/mybb_mybb_1808/forumdisplay.php 2025-12-06 11:32:55.938174543 +0000@@ -314,7 +314,7 @@ if($user['invisible'] != 1 || $mybb->usergroup['canviewwolinvis'] == 1 || $user['uid'] == $mybb->user['uid']) {- $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']);+ $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); $user['profilelink'] = build_profile_link($user['username'], $user['uid']); eval("\$onlinemembers .= \"".$templates->get("forumdisplay_usersbrowsing_user", 1, 0)."\";"); $comma = $lang->comma;@@ -798,6 +798,9 @@ $announcement['subject'] = $parser->parse_badwords($announcement['subject']); $announcement['subject'] = htmlspecialchars_uni($announcement['subject']); $postdate = my_date('relative', $announcement['startdate']);++ $announcement['username'] = htmlspecialchars_uni($announcement['username']);+ $announcement['profilelink'] = build_profile_link($announcement['username'], $announcement['uid']); if($mybb->settings['allowthreadratings'] != 0 && $foruminfo['allowtratings'] != 0 && $fpermissions['canviewthreads'] != 0)@@ -1027,11 +1030,11 @@ $thread['author'] = $thread['uid']; if(!$thread['username']) {- $thread['username'] = $thread['threadusername'];- $thread['profilelink'] = $thread['threadusername'];+ $thread['username'] = $thread['profilelink'] = htmlspecialchars_uni($thread['threadusername']); } else {+ $thread['username'] = htmlspecialchars_uni($thread['username']); $thread['profilelink'] = build_profile_link($thread['username'], $thread['uid']); } @@ -1256,7 +1259,7 @@ $inline_edit_class = "subject_editable"; } - $lastposter = $thread['lastposter'];+ $lastposter = htmlspecialchars_uni($thread['lastposter']); $lastposteruid = $thread['lastposteruid']; $lastpostdate = my_date('relative', $thread['lastpost']);
Vulnerability Existed: yes TRUE POSITIVE Cross-Site Scripting (XSS) - CWE-79 - forumdisplay.php Lines 317, 801, 1033, 1037, 1259 Old Code: ```php $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']); $announcement['username'] = $announcement['username']; // (implicit, no escaping) $thread['username'] = $thread['threadusername']; $thread['username'] = $thread['username']; // (no escaping before use) $lastposter = $thread['lastposter']; ``` Fixed Code: ```php $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); $announcement['username'] = htmlspecialchars_uni($announcement['username']); $thread['username'] = $thread['profilelink'] = htmlspecialchars_uni($thread['threadusername']); $thread['username'] = htmlspecialchars_uni($thread['username']); $lastposter = htmlspecialchars_uni($thread['lastposter']); ``` Explanation: This diff addresses multiple Stored XSS vulnerabilities in MyBB's forumdisplay.php template. User-controlled data fields (`username`, `lastposter`, `threadusername`) are output directly into HTML templates via eval() and template rendering without proper HTML entity encoding. The fix applies `htmlspecialchars_uni()` to escape these values before output, preventing attackers from injecting malicious JavaScript through usernames or poster names. This is a classic output encoding vulnerability where user input stored in the database was rendered in HTML context without escaping. The vulnerability would allow authenticated or unauthenticated attackers to inject XSS payloads through user profiles or thread creation, which would execute in the browsers of other users viewing the forum.
--- cache/mybb_mybb_1807/global.php 2025-12-06 11:32:55.134122623 +0000+++ cache/mybb_mybb_1808/global.php 2025-12-06 11:32:55.938174543 +0000@@ -54,7 +54,7 @@ $session->init(); $mybb->session = &$session; -$mybb->user['ismoderator'] = is_moderator('', '', $mybb->user['uid']);+$mybb->user['ismoderator'] = is_moderator(0, '', $mybb->user['uid']); // Set our POST validation code here $mybb->post_code = generate_post_check();@@ -375,7 +375,7 @@ } // Are we linking to a remote theme server?-if(my_substr($theme['imgdir'], 0, 7) == 'http://' || my_substr($theme['imgdir'], 0, 8) == 'https://')+if(my_validate_url($theme['imgdir'])) { // If a language directory for the current language exists within the theme - we use it if(!empty($mybb->user['language']))@@ -449,10 +449,12 @@ $templatelist = ''; } -$templatelist .= "headerinclude,header,footer,gobutton,htmldoctype,header_welcomeblock_member,header_welcomeblock_guest,header_welcomeblock_member_admin,global_pm_alert,global_unreadreports,error,footer_languageselect_option,footer_contactus";-$templatelist .= ",global_pending_joinrequests,global_awaiting_activation,nav,nav_sep,nav_bit,nav_sep_active,nav_bit_active,footer_languageselect,footer_themeselect,header_welcomeblock_member_moderator,redirect,header_menu_calendar,nav_dropdown,footer_themeselector,task_image";-$templatelist .= ",global_boardclosed_warning,global_bannedwarning,error_inline,error_nopermission_loggedin,error_nopermission,debug_summary,header_quicksearch,header_menu_search,header_menu_portal,header_menu_memberlist,usercp_themeselector_option,smilie,global_board_offline_modal";-$templatelist .= ",video_dailymotion_embed,video_facebook_embed,video_liveleak_embed,video_metacafe_embed,video_myspacetv_embed,video_veoh_embed,video_vimeo_embed,video_yahoo_embed,video_youtube_embed";+$templatelist .= "headerinclude,header,footer,gobutton,htmldoctype,header_welcomeblock_member,header_welcomeblock_guest,header_welcomeblock_member_moderator,header_welcomeblock_member_admin,footer_languageselect_option";+$templatelist .= ",global_pending_joinrequests,global_awaiting_activation,nav,nav_sep,nav_bit,nav_sep_active,nav_bit_active,footer_languageselect,footer_themeselect,header_menu_calendar,global_unreadreports,smilie";+$templatelist .= ",global_boardclosed_warning,global_bannedwarning,error_inline,error_nopermission_loggedin,error_nopermission,header_quicksearch,header_menu_search,header_menu_portal,header_menu_memberlist,redirect";+$templatelist .= ",video_dailymotion_embed,video_facebook_embed,video_liveleak_embed,video_metacafe_embed,video_myspacetv_embed,video_veoh_embed,video_vimeo_embed,video_yahoo_embed,video_youtube_embed,global_dst_detection";+$templatelist .= ",smilieinsert_row,smilieinsert_row_empty,smilieinsert,smilieinsert_getmore,smilieinsert_smilie,global_board_offline_modal,footer_themeselector,task_image,usercp_themeselector_option,debug_summary";+$templatelist .= ",mycode_code,mycode_email,mycode_img,mycode_php,mycode_quote_post,mycode_size_int,mycode_url,global_no_permission_modal,global_boardclosed_reason,nav_dropdown,footer_contactus,global_pm_alert,error"; $templates->cache($db->escape_string($templatelist)); // Set the current date and time now@@ -499,7 +501,7 @@ } // Format the welcome back message- $lang->welcome_back = $lang->sprintf($lang->welcome_back, build_profile_link($mybb->user['username'], $mybb->user['uid']), $lastvisit);+ $lang->welcome_back = $lang->sprintf($lang->welcome_back, build_profile_link(htmlspecialchars_uni($mybb->user['username']), $mybb->user['uid']), $lastvisit); // Tell the user their PM usage $lang->welcome_pms_usage = $lang->sprintf($lang->welcome_pms_usage, my_number_format($mybb->user['pms_unread']), my_number_format($mybb->user['pms_total']));@@ -589,7 +591,7 @@ $unreadreports = ''; // This user is a moderator, super moderator or administrator-if($mybb->usergroup['cancp'] == 1 || ($mybb->user['ismoderator'] && $mybb->usergroup['canmodcp'] == 1 && $mybb->usergroup['canmanagereportedcontent'] == 1))+if($mybb->settings['reportmethod'] == "db" && ($mybb->usergroup['cancp'] == 1 || ($mybb->user['ismoderator'] && $mybb->usergroup['canmodcp'] == 1 && $mybb->usergroup['canmanagereportedcontent'] == 1))) { // Only worth checking if we are here because we have ACP permissions and the other condition fails if($mybb->usergroup['cancp'] == 1 && !($mybb->user['ismoderator'] && $mybb->usergroup['canmodcp'] == 1 && $mybb->usergroup['canmanagereportedcontent'] == 1))@@ -743,6 +745,7 @@ } else {+ $pm['fromusername'] = htmlspecialchars_uni($pm['fromusername']); $user_text = build_profile_link($pm['fromusername'], $pm['fromuid']); } @@ -884,7 +887,7 @@ $contact_us = ''; if(($mybb->settings['contactlink'] == "contact.php" && $mybb->settings['contact'] == 1 && ($mybb->settings['contact_guests'] != 1 && $mybb->user['uid'] == 0 || $mybb->user['uid'] > 0)) || $mybb->settings['contactlink'] != "contact.php") {- if(my_substr($mybb->settings['contactlink'], 0, 1) != '/' && my_substr($mybb->settings['contactlink'], 0, 7) != 'http://' && my_substr($mybb->settings['contactlink'], 0, 8) != 'https://' && my_substr($mybb->settings['contactlink'], 0, 7) != 'mailto:')+ if(!my_validate_url($mybb->settings['contactlink'], true) && my_substr($mybb->settings['contactlink'], 0, 7) != 'mailto:') { $mybb->settings['contactlink'] = $mybb->settings['bburl'].'/'.$mybb->settings['contactlink']; }@@ -896,8 +899,10 @@ $auto_dst_detection = ''; if($mybb->user['uid'] > 0 && $mybb->user['dstcorrection'] == 2) {- $auto_dst_detection = "<script type=\"text/javascript\">if(MyBB) { $([document, window]).bind(\"load\", function() { MyBB.detectDSTChange('".($mybb->user['timezone']+$mybb->user['dst'])."'); }); }</script>\n";+ $timezone = $mybb->user['timezone'] + $mybb->user['dst'];+ eval('$auto_dst_detection = "'.$templates->get('global_dst_detection').'";'); }+ eval('$footer = "'.$templates->get('footer').'";'); // Add our main parts to the navigation@@ -940,7 +945,8 @@ $mybb->settings['boardclosed_reason'] = $lang->boardclosed_reason; } - $lang->error_boardclosed .= "<blockquote>{$mybb->settings['boardclosed_reason']}</blockquote>";+ eval('$reason = "'.$templates->get('global_boardclosed_reason').'";');+ $lang->error_boardclosed .= $reason; if(!$mybb->get_input('modal')) {@@ -1008,6 +1014,8 @@ } } +$output = '';+$notallowed = false; if($mybb->usergroup['canview'] != 1) { // Check pages allowable even when not allowed to view board@@ -1018,19 +1026,33 @@ $allowable_actions = explode(',', ALLOWABLE_PAGE); if(!in_array($mybb->get_input('action'), $allowable_actions)) {- error_no_permission();+ $notallowed = true; } unset($allowable_actions); } else if(ALLOWABLE_PAGE !== 1) {- error_no_permission();+ $notallowed = true; } } else {- error_no_permission();+ $notallowed = true;+ }++ if($notallowed == true)+ {+ if(!$mybb->get_input('modal'))+ {+ error_no_permission();+ }+ else+ {+ eval('$output = "'.$templates->get('global_no_permission_modal', 1, 0).'";');+ echo($output);+ exit;+ } } }
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - global.php lines 504, 748
[Old Code]
Line 504: `$lang->welcome_back = $lang->sprintf($lang->welcome_back, build_profile_link($mybb->user['username'], $mybb->user['uid']), $lastvisit);`
Line 748: `$user_text = build_profile_link($pm['fromusername'], $pm['fromuid']);`
[Fixed Code]
Line 504: `$lang->welcome_back = $lang->sprintf($lang->welcome_back, build_profile_link(htmlspecialchars_uni($mybb->user['username']), $mybb->user['uid']), $lastvisit);`
Line 748: `$pm['fromusername'] = htmlspecialchars_uni($pm['fromusername']);`
`$user_text = build_profile_link($pm['fromusername'], $pm['fromuid']);`
Explanation:
User-controlled data (`$mybb->user['username']` and `$pm['fromusername']`) was being passed directly to `build_profile_link()` without HTML escaping. This could allow stored XSS attacks if these fields contain malicious HTML/JavaScript. The fix applies `htmlspecialchars_uni()` to escape special characters before passing to the profile link builder, preventing injection attacks.
---
Vulnerability Existed: yes
TRUE POSITIVE
Improper Input Validation - CWE-20 - global.php lines 378, 890
[Old Code]
Line 378: `if(my_substr($theme['imgdir'], 0, 7) == 'http://' || my_substr($theme['imgdir'], 0, 8) == 'https://')`
Line 890: `if(my_substr($mybb->settings['contactlink'], 0, 1) != '/' && my_substr($mybb->settings['contactlink'], 0, 7) != 'http://' && my_substr($mybb->settings['contactlink'], 0, 8) != 'https://' && my_substr($mybb->settings['contactlink'], 0, 7) != 'mailto:')`
[Fixed Code]
Line 378: `if(my_validate_url($theme['imgdir']))`
Line 890: `if(!my_validate_url($mybb->settings['contactlink'], true) && my_substr($mybb->settings['contactlink'], 0, 7) != 'mailto:')`
Explanation:
The original code uses fragile string matching to validate URLs, which could be bypassed with encoding tricks or protocol-relative URLs. The fix delegates to a dedicated `my_validate_url()` function, which provides centralized, more robust URL validation. This prevents URL injection attacks and protocol confusion vulnerabilities.
---
Vulnerability Existed: yes
FALSE POSITIVE
Code Injection - CWE-95 - global.php lines 902-903
[Old Code]
Line 902: `$auto_dst_detection = "<script type=\"text/javascript\">if(MyBB) { $([document, window]).bind(\"load\", function() { MyBB.detectDSTChange('".($mybb->user['timezone']+$mybb->user['dst'])."'); }); }</script>\n";`
[Fixed Code]
Lines 902-903:
`$timezone = $mybb->user['timezone'] + $mybb->user['dst'];`
`eval('$auto_dst_detection = "'.$templates->get('global_dst_detection').'";');`
Explanation:
The original code constructs JavaScript inline with user data, presenting an XSS vulnerability. The fix moves the template to a separate template file (`global_dst_detection`) and uses template evaluation with the timezone variable passed separately, reducing the attack surface and improving separation of concerns. This prevents script injection via timezone values.
---
Vulnerability Existed: not sure
Code Injection - CWE-95 - global.php lines 947-948
[Old Code]
Line 947: `$lang->error_boardclosed .= "<blockquote>{$mybb->settings['boardclosed_reason']}</blockquote>";`
[Fixed Code]
Lines 947-948:
`eval('$reason = "'.$templates->get('global_boardclosed_reason').'";');`
`$lang->error_boardclosed .= $reason;`
Explanation:
The original code directly concatenates `$mybb->settings['boardclosed_reason']` which is user-controlled data (admin setting). While the fix moves to a template, it still uses `eval()` which introduces code injection risk if the template system doesn't properly sanitize. However, if the template system properly escapes the `$mybb->settings['boardclosed_reason']` variable when rendering, this may be safer. The security improvement depends on template system safeguards.
---
Vulnerability Existed: yes
TRUE POSITIVE
Authentication/Authorization Bypass - CWE-269 - global.php line 594
[Old Code]
Line 594: `if($mybb->usergroup['cancp'] == 1 || ($mybb->user['ismoderator'] && $mybb->usergroup['canmodcp'] == 1 && $mybb->usergroup['canmanagereportedcontent'] == 1))`
[Fixed Code]
Line 594: `if($mybb->settings['reportmethod'] == "db" && ($mybb->usergroup['cancp'] == 1 || ($mybb->user['ismoderator'] && $mybb->usergroup['canmodcp'] == 1 && $mybb->usergroup['canmanagereportedcontent'] == 1)))`
Explanation:
The original code checked user permissions without verifying if the report functionality was actually enabled/configured. Adding the `$mybb->settings['reportmethod'] == "db"` check prevents unauthorized access to report functions when the database reporting method is disabled, fixing a logic-level authorization vulnerability.
--- cache/mybb_mybb_1807/inc/cachehandlers/apc.php 2025-12-06 11:32:55.174125206 +0000+++ cache/mybb_mybb_1808/inc/cachehandlers/apc.php 2025-12-06 11:32:55.958175834 +0000@@ -105,7 +105,7 @@ * * @return string */- function size_of($name)+ function size_of($name='') { global $lang;
Vulnerability Existed: no [CWE-665: Improper Initialization] - CWE-665 - inc/cachehandlers/apc.php [108] Old Code: ```php function size_of($name) ``` Fixed Code: ```php function size_of($name='') ``` Explanation: This change adds a default parameter value (`''`) to the `$name` parameter in the `size_of()` function. This is a defensive programming improvement rather than a security vulnerability fix. The change makes the function more robust by allowing it to be called without arguments, which would previously have caused an undefined variable notice. However, this is not a security vulnerability - it's a code quality improvement for parameter handling. The function will still work correctly in both cases, as the empty string would simply result in an APC cache operation on a key named empty string, which is handled appropriately by the caching logic.
--- cache/mybb_mybb_1807/inc/cachehandlers/eaccelerator.php 2025-12-06 11:32:55.174125206 +0000+++ cache/mybb_mybb_1808/inc/cachehandlers/eaccelerator.php 2025-12-06 11:32:55.958175834 +0000@@ -107,7 +107,7 @@ * * @return string */- function size_of($name)+ function size_of($name='') { global $lang;
Vulnerability Existed: no No CWE/Vulnerability Found - N/A - inc/cachehandlers/eaccelerator.php [110] Old Code: ```php function size_of($name) ``` Fixed Code: ```php function size_of($name='') ``` Explanation: This change adds a default parameter value (`$name=''`) to the `size_of()` function. This is not a security fix—it's a code quality improvement. The modification allows the function to be called without arguments, preventing potential "missing argument" errors. This is a defensive programming practice that makes the function more robust, but it does not address or fix any existing security vulnerability. The parameter handling itself does not introduce or remove any security risks related to injection, authentication, authorization, or other common vulnerability classes.
--- cache/mybb_mybb_1807/inc/cachehandlers/interface.php 2025-12-06 11:32:55.174125206 +0000+++ cache/mybb_mybb_1808/inc/cachehandlers/interface.php 2025-12-06 11:32:55.962176093 +0000@@ -57,5 +57,5 @@ * * @return string */- function size_of($name);+ function size_of($name=''); }
Vulnerability Existed: no [No Vulnerability] - [N/A] - [inc/cachehandlers/interface.php] [Lines 60] Old Code: ```php function size_of($name); ``` Fixed Code: ```php function size_of($name=''); ``` Explanation: This change adds a default parameter value to the `size_of()` method signature in the cache handler interface. This is a non-security change that modifies the method signature to provide a default empty string value for the `$name` parameter. This is a backwards-compatible enhancement that allows the method to be called without arguments, but it does not fix or relate to any security vulnerability. No CWE or vulnerability is present in either version.
--- cache/mybb_mybb_1807/inc/cachehandlers/memcache.php 2025-12-06 11:32:55.174125206 +0000+++ cache/mybb_mybb_1808/inc/cachehandlers/memcache.php 2025-12-06 11:32:55.962176093 +0000@@ -147,7 +147,7 @@ * * @return string */- function size_of($name)+ function size_of($name='') { global $lang;
Vulnerability Existed: no [N/A] - [N/A] - inc/cachehandlers/memcache.php [150] Old Code: ```php function size_of($name) ``` Fixed Code: ```php function size_of($name='') ``` Explanation: This is not a security fix. The change adds a default parameter value (`''`) to the `size_of()` function's `$name` parameter. This is a code quality improvement that prevents potential "undefined variable" notices or errors when the function is called without arguments, but it does not address any security vulnerability. The parameter assignment does not introduce or remove any security-related issues such as injection, authentication bypass, privilege escalation, or data exposure.
--- cache/mybb_mybb_1807/inc/cachehandlers/memcached.php 2025-12-06 11:32:55.174125206 +0000+++ cache/mybb_mybb_1808/inc/cachehandlers/memcached.php 2025-12-06 11:32:55.962176093 +0000@@ -147,7 +147,7 @@ * * @return string */- function size_of($name)+ function size_of($name='') { global $lang;
Vulnerability Existed: no Default Parameter Assignment - No CWE - inc/cachehandlers/memcached.php - Line 150 [Old Code] function size_of($name) [Fixed Code] function size_of($name='') Explanation: This change adds a default empty string value to the `$name` parameter. This is a defensive programming improvement that prevents potential errors when the function is called without arguments, but it does not address or fix an existing security vulnerability. The modification simply makes the function more robust by providing a safe default value. There is no evidence of a security flaw being fixed here—this is a code quality improvement rather than a security fix.
--- cache/mybb_mybb_1807/inc/cachehandlers/xcache.php 2025-12-06 11:32:55.174125206 +0000+++ cache/mybb_mybb_1808/inc/cachehandlers/xcache.php 2025-12-06 11:32:55.962176093 +0000@@ -102,7 +102,7 @@ * * @return string */- function size_of($name)+ function size_of($name='') { global $lang;
Vulnerability Existed: no [CWE Name] - [CWE ID] - inc/cachehandlers/xcache.php [105] Old Code: ```php function size_of($name) ``` Fixed Code: ```php function size_of($name='') ``` Explanation: This change adds a default parameter value to the `size_of()` function by providing an empty string as the default value for the `$name` parameter. This is not a security fix but rather a code quality improvement that prevents potential "missing argument" errors when the function is called without parameters. The change makes the function more robust by ensuring `$name` always has a defined value (empty string if not provided), but it does not address or remediate any existing security vulnerability. This is a defensive programming practice rather than a security vulnerability fix.
--- cache/mybb_mybb_1807/inc/class_core.php 2025-12-06 11:32:55.174125206 +0000+++ cache/mybb_mybb_1808/inc/class_core.php 2025-12-06 11:32:55.966176352 +0000@@ -14,14 +14,14 @@ * * @var string */- public $version = "1.8.7";+ public $version = "1.8.8"; /** * The version code of MyBB we're running. * * @var integer */- public $version_code = 1807;+ public $version_code = 1808; /** * The current working directory.@@ -553,7 +553,7 @@ $error_code = MYBB_NOT_UPGRADED; break; case "sql_load_error":- $message = "MyBB was unable to load the SQL extension. Please contact the MyBB Group for support. <a href=\"http://www.mybb.com\">MyBB Website</a>";+ $message = "MyBB was unable to load the SQL extension. Please contact the MyBB Group for support. <a href=\"https://mybb.com\">MyBB Website</a>"; $error_code = MYBB_SQL_LOAD_ERROR; break; case "apc_load_error":@@ -577,7 +577,7 @@ $error_code = MYBB_CACHEHANDLER_LOAD_ERROR; break; default:- $message = "MyBB has experienced an internal error. Please contact the MyBB Group for support. <a href=\"http://www.mybb.com\">MyBB Website</a>";+ $message = "MyBB has experienced an internal error. Please contact the MyBB Group for support. <a href=\"https://mybb.com\">MyBB Website</a>"; $error_code = MYBB_GENERAL; } $error_handler->trigger($message, $error_code);@@ -598,7 +598,7 @@ */ $grouppermignore = array("gid", "type", "title", "description", "namestyle", "usertitle", "stars", "starimage", "image");-$groupzerogreater = array("pmquota", "maxpmrecipients", "maxreputationsday", "attachquota", "maxemails", "maxwarningsday", "maxposts", "edittimelimit", "canusesigxposts", "maxreputationsperthread", "emailfloodtime");+$groupzerogreater = array("pmquota", "maxpmrecipients", "maxreputationsday", "attachquota", "maxemails", "maxwarningsday", "maxposts", "edittimelimit", "canusesigxposts", "maxreputationsperuser", "maxreputationsperthread", "emailfloodtime"); $displaygroupfields = array("title", "description", "namestyle", "usertitle", "stars", "starimage", "image"); // These are fields in the usergroups table that are also forum permission specific.@@ -622,4 +622,3 @@ 'canvotepolls', 'cansearch' );-
Analyzing the provided diff for security vulnerabilities: --- **Vulnerability 1:** Vulnerability Existed: yes TRUE POSITIVE Insecure Transport - CWE-319 - inc/class_core.php [556, 580] Old Code: ```php $message = "MyBB was unable to load the SQL extension. Please contact the MyBB Group for support. <a href=\"http://www.mybb.com\">MyBB Website</a>"; ``` and ```php $message = "MyBB has experienced an internal error. Please contact the MyBB Group for support. <a href=\"http://www.mybb.com\">MyBB Website</a>"; ``` Fixed Code: ```php $message = "MyBB was unable to load the SQL extension. Please contact the MyBB Group for support. <a href=\"https://mybb.com\">MyBB Website</a>"; ``` and ```php $message = "MyBB has experienced an internal error. Please contact the MyBB Group for support. <a href=\"https://mybb.com\">MyBB Website</a>"; ``` Explanation: The vulnerability existed because the error messages contained hardcoded HTTP links to `http://www.mybb.com`. Using HTTP for external links is insecure as it allows man-in-the-middle attacks where an attacker could intercept the connection and potentially redirect users to malicious sites or inject content. The fix upgrades both URLs to HTTPS (`https://mybb.com`), ensuring encrypted communication and protecting against interception attacks. Additionally, the domain was simplified from `www.mybb.com` to `mybb.com`, which is a cleaner practice. --- **Other Changes:** The remaining changes (version bumps from 1.8.7 to 1.8.8, version_code from 1807 to 1808, and the addition of `"maxreputationsperuser"` to the `$groupzerogreater` array) are not security-related fixes and do not represent vulnerabilities or fixes.
--- cache/mybb_mybb_1807/inc/class_datacache.php 2025-12-06 11:32:55.178125465 +0000+++ cache/mybb_mybb_1808/inc/class_datacache.php 2025-12-06 11:32:55.966176352 +0000@@ -466,7 +466,7 @@ $types = array(); - $query = $db->simple_select("attachtypes", "*");+ $query = $db->simple_select('attachtypes', '*', 'enabled=1'); while($type = $db->fetch_array($query)) { $type['extension'] = my_strtolower($type['extension']);@@ -787,7 +787,7 @@ $data = array( 'users' => $awaitingusers,- 'time' => TIME_NOW + 'time' => TIME_NOW ); $this->update('awaitingactivation', $data);@@ -896,25 +896,10 @@ $query = $db->simple_select("reportedcontent", "dateline", "reportstatus='0'", array('order_by' => 'dateline', 'order_dir' => 'DESC')); $latest = $db->fetch_array($query); - $reasons = array();-- if(!empty($mybb->settings['reportreasons']))- {- $options = $mybb->settings['reportreasons'];- $options = explode("\n", $options);-- foreach($options as $option)- {- $option = explode("=", $option);- $reasons[$option[0]] = $option[1];- }- }- $reports = array( "unread" => $num['unreadcount'], "total" => $total['reportcount'],- "lastdateline" => $latest['dateline'],- "reasons" => $reasons+ "lastdateline" => $latest['dateline'] ); $this->update("reportedcontent", $reports);@@ -1241,6 +1226,54 @@ $this->update("profilefields", $fields); } + /**+ * Update the report reasons cache.+ *+ */+ function update_reportreasons($no_plugins = false)+ {+ global $db;++ $content_types = array('post', 'profile', 'reputation');+ if(!$no_plugins)+ {+ global $plugins;+ $content_types = $plugins->run_hooks("report_content_types", $content_types);+ }++ $reasons = array();++ $query = $db->simple_select("reportreasons", "*", "", array('order_by' => 'disporder'));+ while($reason = $db->fetch_array($query))+ {+ if($reason['appliesto'] == 'all')+ {+ foreach($content_types as $content)+ {+ $reasons[$content][] = array(+ 'rid' => $reason['rid'],+ 'title' => $reason['title'],+ 'extra' => $reason['extra'],+ );+ }+ }+ elseif($reason['appliesto'] != '')+ {+ $appliesto = explode(",", $reason['appliesto']);+ foreach($appliesto as $content)+ {+ $reasons[$content][] = array(+ 'rid' => $reason['rid'],+ 'title' => $reason['title'],+ 'extra' => $reason['extra'],+ );+ }+ }+ }++ $this->update("reportreasons", $reasons);+ }+ /* Other, extra functions for reloading caches if we just changed to another cache extension (i.e. from db -> xcache) */ function reload_mostonline() {
Analyzing the provided code diff for security vulnerabilities:
**Vulnerability 1:**
Vulnerability Existed: yes
SQL Injection / Improper Input Validation - CWE-89 - inc/class_datacache.php lines 896-912
[Old Code]
```php
$reasons = array();
if(!empty($mybb->settings['reportreasons']))
{
$options = $mybb->settings['reportreasons'];
$options = explode("\n", $options);
foreach($options as $option)
{
$option = explode("=", $option);
$reasons[$option[0]] = $option[1];
}
}
```
[Fixed Code]
```php
// Code removed - report reasons now sourced from database via update_reportreasons()
```
Explanation:
The original code parsed report reasons directly from `$mybb->settings['reportreasons']` using string manipulation (explode on "\n" and "="). This approach is vulnerable to injection attacks if the settings value is not properly validated. By replacing this with a dedicated `update_reportreasons()` function that queries the database table `reportreasons`, the code now retrieves structured data directly from the database with proper handling, eliminating the risk of malformed input being parsed and stored in the cache.
**Vulnerability 2:**
Vulnerability Existed: yes
TRUE POSITIVE
Insufficient Data Filtering / Information Disclosure - CWE-200 - inc/class_datacache.php line 469
[Old Code]
```php
$query = $db->simple_select("attachtypes", "*");
```
[Fixed Code]
```php
$query = $db->simple_select('attachtypes', '*', 'enabled=1');
```
Explanation:
The original query selected all attachment types without filtering. The fix adds a WHERE clause condition `'enabled=1'` to only retrieve enabled attachment types. This prevents disabled (potentially dangerous or deprecated) attachment types from being cached and made available to the application, reducing the attack surface by ensuring only administratively-enabled file types are processed.
--- cache/mybb_mybb_1807/inc/class_error.php 2025-12-06 11:32:55.186125981 +0000+++ cache/mybb_mybb_1808/inc/class_error.php 2025-12-06 11:32:55.966176352 +0000@@ -542,7 +542,7 @@ <body> <div id="container"> <div id="logo">- <h1><a href="http://www.mybb.com/" title="MyBB"><span class="invisible">MyBB</span></a></h1>+ <h1><a href="https://mybb.com/" title="MyBB"><span class="invisible">MyBB</span></a></h1> </div> <div id="content">@@ -550,7 +550,7 @@ <div id="error"> {$error_message}- <p id="footer">Please contact the <a href="http://www.mybb.com">MyBB Group</a> for technical support.</p>+ <p id="footer">Please contact the <a href="https://mybb.com">MyBB Group</a> for technical support.</p> </div> </div> </div>@@ -575,7 +575,7 @@ <h2>{$title}</h2> <div id="mybb_error_error"> {$error_message}- <p id="mybb_error_footer">Please contact the <a href="http://www.mybb.com">MyBB Group</a> for technical support.</p>+ <p id="mybb_error_footer">Please contact the <a href="https://mybb.com">MyBB Group</a> for technical support.</p> </div> </div> EOF;
Vulnerability Existed: no [Protocol Downgrade Prevention] - [Not a CWE vulnerability, but a security best practice] - inc/class_error.php [lines 545, 553, 578] [Old Code] ``` <h1><a href="http://www.mybb.com/" title="MyBB"><span class="invisible">MyBB</span></a></h1> <p id="footer">Please contact the <a href="http://www.mybb.com">MyBB Group</a> for technical support.</p> <p id="mybb_error_footer">Please contact the <a href="http://www.mybb.com">MyBB Group</a> for technical support.</p> ``` [Fixed Code] ``` <h1><a href="https://mybb.com/" title="MyBB"><span class="invisible">MyBB</span></a></h1> <p id="footer">Please contact the <a href="https://mybb.com">MyBB Group</a> for technical support.</p> <p id="mybb_error_footer">Please contact the <a href="https://mybb.com">MyBB Group</a> for technical support.</p> ``` Explanation: This is not a vulnerability fix per se, but rather a security enhancement and modernization. The changes upgrade HTTP URLs to HTTPS, which: 1. Prevents potential man-in-the-middle (MITM) attacks when users click these links 2. Ensures encrypted communication with the external MyBB website 3. Aligns with modern security best practices (HTTPS is now standard) 4. Also removes "www." subdomain, which is a modern convention simplification No actual code vulnerability existed in the original version—these were just unencrypted external links. The fix improves security posture by enforcing encrypted connections.
--- cache/mybb_mybb_1807/inc/class_feedgeneration.php 2025-12-06 11:32:55.186125981 +0000+++ cache/mybb_mybb_1808/inc/class_feedgeneration.php 2025-12-06 11:32:55.966176352 +0000@@ -97,7 +97,7 @@ $this->xml .= "\t<id>{$this->channel['link']}</id>\n"; $this->xml .= "\t<link rel=\"alternate\" type=\"text/html\" href=\"{$this->channel['link']}\"/>\n"; $this->xml .= "\t<updated>{$this->channel['date']}</updated>\n";- $this->xml .= "\t<generator uri=\"http://www.mybb.com\">MyBB</generator>\n";+ $this->xml .= "\t<generator uri=\"https://mybb.com\">MyBB</generator>\n"; break; // The default is the RSS 2.0 format. default:
Vulnerability Existed: no No Vulnerability Detected - [Information Disclosure Prevention] - inc/class_feedgeneration.php [100] Old Code: ``` $this->xml .= "\t<generator uri=\"http://www.mybb.com\">MyBB</generator>\n"; ``` Fixed Code: ``` $this->xml .= "\t<generator uri=\"https://mybb.com\">MyBB</generator>\n"; ``` Explanation: This change upgrades the URI from HTTP to HTTPS and removes the "www" subdomain. This is a security best practice that addresses potential information disclosure and man-in-the-middle attack vectors. The original code exposed the generator metadata over an unencrypted HTTP connection in the feed XML, which could be intercepted. Additionally, using HTTPS ensures encrypted communication when external systems reference this URI. While this is not a critical vulnerability in the feed XML itself (as it's metadata), it represents a security improvement by: 1. **Protocol Security**: HTTPS provides encryption and authentication, preventing potential tampering with the generator URI reference 2. **Best Practice**: Modern web applications should use HTTPS for all external URIs to maintain consistent security posture 3. **Information Disclosure**: Reduces exposure of the link over unencrypted channels This is a security hardening measure rather than fixing an exploitable vulnerability in the code itself.
--- cache/mybb_mybb_1807/inc/class_mailhandler.php 2025-12-06 11:32:55.186125981 +0000+++ cache/mybb_mybb_1808/inc/class_mailhandler.php 2025-12-06 11:32:55.966176352 +0000@@ -153,7 +153,6 @@ } else {- $this->from = ""; if($mybb->settings['mail_handler'] == 'smtp') { $this->from = $this->get_from_email();
Vulnerability Existed: no [Improper Initialization] - [No CWE] - inc/class_mailhandler.php [156] Old Code: ``` $this->from = ""; ``` Fixed Code: ``` (line removed) ``` Explanation: The removed line was redundant initialization of `$this->from` to an empty string. This is not a security vulnerability. The variable is properly initialized shortly after through the `$this->get_from_email()` method call, which sets it to a legitimate email address. Removing this redundant assignment improves code efficiency without introducing any security risk. The `$this->from` property is set based on the mail handler configuration, and the initialization path ensures it gets a proper value before being used.
--- cache/mybb_mybb_1807/inc/class_moderation.php 2025-12-06 11:32:55.198126756 +0000+++ cache/mybb_mybb_1808/inc/class_moderation.php 2025-12-06 11:32:55.966176352 +0000@@ -801,6 +801,7 @@ $fid = $post['fid']; $mastertid = $post['tid']; $first = 0;+ $visible = $post['visible']; } else {@@ -844,6 +845,7 @@ { --$user_counters[$post['uid']]['num_threads']; }+ $thread_counters[$post['tid']]['attachmentcount'] -= $post['attachmentcount']; } elseif($post['visible'] == 0) {@@ -855,7 +857,6 @@ // Subtract 1 deleted post from post's thread --$thread_counters[$post['tid']]['deletedposts']; }- $thread_counters[$post['tid']]['attachmentcount'] -= $post['attachmentcount']; // Subtract 1 post from post's forum if($post['threadvisible'] == 1 && $post['visible'] == 1)@@ -870,6 +871,12 @@ { --$forum_counters[$post['fid']]['deletedposts']; }++ // Add attachment count to thread+ if($visible == 1)+ {+ $thread_counters[$mastertid]['attachmentcount'] += $post['attachmentcount'];+ } } }
Analyzing the provided diff for security vulnerabilities: Vulnerability Existed: no No Vulnerabilities Detected - inc/class_moderation.php Explanation: This diff contains logic corrections and refactoring of post/thread counter management in a MyBB moderation class, not security fixes. The changes: 1. **Line 804**: Added `$visible = $post['visible'];` - initializes a variable for the first post's visibility status 2. **Lines 847-848**: Moved attachment count subtraction inside the conditional block where it logically belongs (when post is visible or deleted) 3. **Lines 873-879**: Added logic to increment attachment count on the master thread when visibility is 1 These are **data integrity corrections**, not security vulnerabilities. The changes ensure: - Attachment counts are properly maintained for thread hierarchies - Visibility state is correctly tracked and used - Counter operations occur in the appropriate conditional branches No SQL injection, authentication bypass, authorization flaws, XSS, CSRF, or other security vulnerabilities are present in this diff. The modifications appear to fix logic bugs where attachment counts were being decremented universally regardless of post status, when they should be handled conditionally based on visibility state.
--- cache/mybb_mybb_1807/inc/class_parser.php 2025-12-06 11:32:55.198126756 +0000+++ cache/mybb_mybb_1808/inc/class_parser.php 2025-12-06 11:32:55.970176609 +0000@@ -89,6 +89,14 @@ public $list_count; /**+ * Whether or not should a <br /> with clear: both be added at the end of the parsed message+ *+ * @access public+ * @var boolean+ */+ public $clear_needed = false;++ /** * Parses a message with the specified options. * * @param string $message The message to be parsed.@@ -99,6 +107,8 @@ { global $plugins, $mybb; + $this->clear_needed = false;+ // Set base URL for parsing smilies $this->base_url = $mybb->settings['bburl']; @@ -161,8 +171,8 @@ { global $lang; - $message = preg_replace('#(>|^|\r|\n)/me ([^\r\n<]*)#i', "\\1<span style=\"color: red;\">* {$this->options['me_username']} \\2</span>", $message);- $message = preg_replace('#(>|^|\r|\n)/slap ([^\r\n<]*)#i', "\\1<span style=\"color: red;\">* {$this->options['me_username']} {$lang->slaps} \\2 {$lang->with_trout}</span>", $message);+ $message = preg_replace('#(>|^|\r|\n)/me ([^\r\n<]*)#i', "\\1<span style=\"color: red;\" class=\"mycode_me\">* {$this->options['me_username']} \\2</span>", $message);+ $message = preg_replace('#(>|^|\r|\n)/slap ([^\r\n<]*)#i', "\\1<span style=\"color: red;\" class=\"mycode_slap\">* {$this->options['me_username']} {$lang->slaps} \\2 {$lang->with_trout}</span>", $message); } // If we can, parse smilies@@ -217,6 +227,11 @@ $message = preg_replace("#( )+(</?(?:html|head|body|div|p|form|table|thead|tbody|tfoot|tr|td|th|ul|ol|li|div|p|blockquote|cite|hr)[^>]*>)#i", "$2", $message); } + if($this->clear_needed)+ {+ $message .= '<br class="clear" />';+ }+ $message = $plugins->run_hooks("parse_message_end", $message); return $message;@@ -252,19 +267,19 @@ if($mybb->settings['allowbasicmycode'] == 1) { $standard_mycode['b']['regex'] = "#\[b\](.*?)\[/b\]#si";- $standard_mycode['b']['replacement'] = "<span style=\"font-weight: bold;\">$1</span>";+ $standard_mycode['b']['replacement'] = "<span style=\"font-weight: bold;\" class=\"mycode_b\">$1</span>"; $standard_mycode['u']['regex'] = "#\[u\](.*?)\[/u\]#si";- $standard_mycode['u']['replacement'] = "<span style=\"text-decoration: underline;\">$1</span>";+ $standard_mycode['u']['replacement'] = "<span style=\"text-decoration: underline;\" class=\"mycode_u\">$1</span>"; $standard_mycode['i']['regex'] = "#\[i\](.*?)\[/i\]#si";- $standard_mycode['i']['replacement'] = "<span style=\"font-style: italic;\">$1</span>";+ $standard_mycode['i']['replacement'] = "<span style=\"font-style: italic;\" class=\"mycode_i\">$1</span>"; $standard_mycode['s']['regex'] = "#\[s\](.*?)\[/s\]#si";- $standard_mycode['s']['replacement'] = "<del>$1</del>";+ $standard_mycode['s']['replacement'] = "<span style=\"text-decoration: line-through;\" class=\"mycode_s\">$1</span>"; $standard_mycode['hr']['regex'] = "#\[hr\]#si";- $standard_mycode['hr']['replacement'] = "<hr />";+ $standard_mycode['hr']['replacement'] = "<hr class=\"mycode_hr\" />"; ++$standard_count; }@@ -314,7 +329,7 @@ if($mybb->settings['allowcolormycode'] == 1) { $nestable_mycode['color']['regex'] = "#\[color=([a-zA-Z]*|\#?[\da-fA-F]{3}|\#?[\da-fA-F]{6})](.*?)\[/color\]#si";- $nestable_mycode['color']['replacement'] = "<span style=\"color: $1;\">$2</span>";+ $nestable_mycode['color']['replacement'] = "<span style=\"color: $1;\" class=\"mycode_color\">$2</span>"; ++$nestable_count; }@@ -322,7 +337,7 @@ if($mybb->settings['allowsizemycode'] == 1) { $nestable_mycode['size']['regex'] = "#\[size=(xx-small|x-small|small|medium|large|x-large|xx-large)\](.*?)\[/size\]#si";- $nestable_mycode['size']['replacement'] = "<span style=\"font-size: $1;\">$2</span>";+ $nestable_mycode['size']['replacement'] = "<span style=\"font-size: $1;\" class=\"mycode_size\">$2</span>"; $callback_mycode['size_int']['regex'] = "#\[size=([0-9\+\-]+?)\](.*?)\[/size\]#si"; $callback_mycode['size_int']['replacement'] = array($this, 'mycode_handle_size_callback');@@ -334,7 +349,7 @@ if($mybb->settings['allowfontmycode'] == 1) { $nestable_mycode['font']['regex'] = "#\[font=([a-z0-9 ,\-_'\"]+)\](.*?)\[/font\]#si";- $nestable_mycode['font']['replacement'] = "<span style=\"font-family: $1;\">$2</span>";+ $nestable_mycode['font']['replacement'] = "<span style=\"font-family: $1;\" class=\"mycode_font\">$2</span>"; ++$nestable_count; }@@ -342,7 +357,7 @@ if($mybb->settings['allowalignmycode'] == 1) { $nestable_mycode['align']['regex'] = "#\[align=(left|center|right|justify)\](.*?)\[/align\]#si";- $nestable_mycode['align']['replacement'] = "<div style=\"text-align: $1;\">$2</div>";+ $nestable_mycode['align']['replacement'] = "<div style=\"text-align: $1;\" class=\"mycode_align\">$2</div>"; ++$nestable_count; }@@ -466,16 +481,16 @@ if(!empty($this->options['allow_imgcode'])) { $message = preg_replace_callback("#\[img\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_callback1'), $message);- $message = preg_replace_callback("#\[img=([0-9]{1,3})x([0-9]{1,3})\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_callback2'), $message);- $message = preg_replace_callback("#\[img align=([a-z]+)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_callback3'), $message);- $message = preg_replace_callback("#\[img=([0-9]{1,3})x([0-9]{1,3}) align=([a-z]+)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_callback4'), $message);+ $message = preg_replace_callback("#\[img=([1-9][0-9]*)x([1-9][0-9]*)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_callback2'), $message);+ $message = preg_replace_callback("#\[img align=(left|right)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_callback3'), $message);+ $message = preg_replace_callback("#\[img=([1-9][0-9]*)x([1-9][0-9]*) align=(left|right)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_callback4'), $message); } else { $message = preg_replace_callback("#\[img\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_disabled_callback1'), $message);- $message = preg_replace_callback("#\[img=([0-9]{1,3})x([0-9]{1,3})\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_disabled_callback2'), $message);- $message = preg_replace_callback("#\[img align=([a-z]+)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_disabled_callback3'), $message);- $message = preg_replace_callback("#\[img=([0-9]{1,3})x([0-9]{1,3}) align=([a-z]+)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_disabled_callback4'), $message);+ $message = preg_replace_callback("#\[img=([1-9][0-9]*)x([1-9][0-9]*)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_disabled_callback2'), $message);+ $message = preg_replace_callback("#\[img align=(left|right)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_disabled_callback3'), $message);+ $message = preg_replace_callback("#\[img=([1-9][0-9]*)x([1-9][0-9]*) align=(left|right)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_disabled_callback4'), $message); } // Convert videos when allow.@@ -649,7 +664,7 @@ } /**- * Attempts to move any javascript references in the specified message.+ * Attempts to move any javascript references in the specified message. * * @param string The message to be parsed. * @return string The parsed message.@@ -658,7 +673,7 @@ { $js_array = array( "#(&\#(0*)106;?|&\#(0*)74;?|&\#x(0*)4a;?|&\#x(0*)6a;?|j)((&\#(0*)97;?|&\#(0*)65;?|a)(&\#(0*)118;?|&\#(0*)86;?|v)(&\#(0*)97;?|&\#(0*)65;?|a)(\s)?(&\#(0*)115;?|&\#(0*)83;?|s)(&\#(0*)99;?|&\#(0*)67;?|c)(&\#(0*)114;?|&\#(0*)82;?|r)(&\#(0*)105;?|&\#(0*)73;?|i)(&\#112;?|&\#(0*)80;?|p)(&\#(0*)116;?|&\#(0*)84;?|t)(&\#(0*)58;?|\:))#i",- "#(on)([a-z]+\s?=)#i",+ "#([\s\"']on)([a-z]+\s*=)#i", ); // Add invisible white space@@ -676,16 +691,24 @@ */ function mycode_handle_size($size, $text) {- $size = (int)$size+10;+ global $templates;++ $size = (int)$size;++ if($size < 1)+ {+ $size = 1;+ } if($size > 50) { $size = 50; } - $text = "<span style=\"font-size: {$size}pt;\">".str_replace("\'", "'", $text)."</span>";+ $text = str_replace("\'", "'", $text); - return $text;+ eval("\$mycode_size = \"".$templates->get("mycode_size_int", 1, 0)."\";");+ return $mycode_size; } /**@@ -716,7 +739,7 @@ if($text_only == false) {- $replace = "<blockquote><cite>$lang->quote</cite>$1</blockquote>\n";+ $replace = "<blockquote class=\"mycode_quote\"><cite>$lang->quote</cite>$1</blockquote>\n"; $replace_callback = array($this, 'mycode_parse_post_quotes_callback1'); } else@@ -814,7 +837,7 @@ { $username = my_substr($username, 0, my_strlen($username)-1); }- + if(!empty($this->options['allow_html'])) { $username = htmlspecialchars_uni($username);@@ -832,7 +855,8 @@ $span = "<span>{$date}</span>"; } - return "<blockquote><cite>{$span}{$username} {$lang->wrote}{$linkback}</cite>{$message}</blockquote>\n";+ eval("\$mycode_quote = \"".$templates->get("mycode_quote_post", 1, 0)."\";");+ return $mycode_quote; } } @@ -867,7 +891,7 @@ */ function mycode_parse_code($code, $text_only=false) {- global $lang;+ global $lang, $templates; if($text_only == true) {@@ -890,7 +914,8 @@ $code = str_replace("\t", ' ', $code); $code = str_replace(" ", ' ', $code); - return "<div class=\"codeblock\">\n<div class=\"title\">".$lang->code."\n</div><div class=\"body\" dir=\"ltr\"><code>".$code."</code></div></div>\n";+ eval("\$mycode_code = \"".$templates->get("mycode_code", 1, 0)."\";");+ return $mycode_code; } /**@@ -914,7 +939,7 @@ */ function mycode_parse_php($str, $bare_return = false, $text_only = false) {- global $lang;+ global $lang, $templates; if($text_only == true) {@@ -980,7 +1005,8 @@ } // Send back the code all nice and pretty- return "<div class=\"codeblock phpcodeblock\"><div class=\"title\">$lang->php_code\n</div><div class=\"body\">".$code."</div></div>\n";+ eval("\$mycode_php = \"".$templates->get("mycode_php", 1, 0)."\";");+ return $mycode_php; } /**@@ -1003,6 +1029,7 @@ */ function mycode_parse_url($url, $name="") {+ global $templates; if(!preg_match("#^[a-z0-9]+://#i", $url)) { $url = "http://".$url;@@ -1039,8 +1066,9 @@ $url = str_replace(array_keys($entities), array_values($entities), $url); $name = preg_replace("#&\#([0-9]+);#si", "&#$1;", $name); // Fix & but allow unicode- $link = "<a href=\"$url\" target=\"_blank\"{$nofollow}>$name</a>";- return $link;++ eval("\$mycode_url = \"".$templates->get("mycode_url", 1, 0)."\";");+ return $mycode_url; } /**@@ -1083,7 +1111,7 @@ */ function mycode_parse_img($url, $dimensions=array(), $align='') {- global $lang;+ global $lang, $templates; $url = trim($url); $url = str_replace("\n", "", $url); $url = str_replace("\r", "", $url);@@ -1096,14 +1124,19 @@ $css_align = ''; if($align == "right") {- $css_align = " style=\"float: right;\"";+ $css_align = ' style="float: right;"'; } else if($align == "left") {- $css_align = " style=\"float: left;\"";+ $css_align = ' style="float: left;"';+ }++ if($align)+ {+ $this->clear_needed = true; }- $alt = basename($url); + $alt = basename($url); $alt = htmlspecialchars_decode($alt); if(my_strlen($alt) > 55) {@@ -1112,14 +1145,15 @@ $alt = htmlspecialchars_uni($alt); $alt = $lang->sprintf($lang->posted_image, $alt);+ $width = $height = ''; if(isset($dimensions[0]) && $dimensions[0] > 0 && isset($dimensions[1]) && $dimensions[1] > 0) {- return "<img src=\"{$url}\" width=\"{$dimensions[0]}\" height=\"{$dimensions[1]}\" border=\"0\" alt=\"{$alt}\"{$css_align} />";- }- else- {- return "<img src=\"{$url}\" border=\"0\" alt=\"{$alt}\"{$css_align} />";+ $width = " width=\"{$dimensions[0]}\"";+ $height = " height=\"{$dimensions[1]}\""; }++ eval("\$mycode_img = \"".$templates->get("mycode_img", 1, 0)."\";");+ return $mycode_img; } /**@@ -1237,22 +1271,23 @@ */ function mycode_parse_email($email, $name="") {+ global $templates;+ if(!$name) { $name = $email; } if(preg_match("/^([a-zA-Z0-9-_\+\.]+?)@[a-zA-Z0-9-]+\.[a-zA-Z0-9\.-]+$/si", $email)) {- return "<a href=\"mailto:$email\">".$name."</a>";+ $email = $email; } elseif(preg_match("/^([a-zA-Z0-9-_\+\.]+?)@[a-zA-Z0-9-]+\.[a-zA-Z0-9\.-]+\?(.*?)$/si", $email)) {- return "<a href=\"mailto:".htmlspecialchars_uni($email)."\">".$name."</a>";- }- else- {- return $email;+ $email = htmlspecialchars_uni($email); }++ eval("\$mycode_email = \"".$templates->get("mycode_email", 1, 0)."\";");+ return $mycode_email; } /**@@ -1398,7 +1433,6 @@ $id = htmlspecialchars_uni($id); eval("\$video_code = \"".$templates->get("video_{$video}_embed")."\";");- return $video_code; } @@ -1520,11 +1554,11 @@ if($type) {- $list = "\n<ol type=\"$type\">$message</ol>\n";+ $list = "\n<ol type=\"$type\" class=\"mycode_list\">$message</ol>\n"; } else {- $list = "<ul>$message</ul>\n";+ $list = "<ul class=\"mycode_list\">$message</ul>\n"; } $list = preg_replace("#<(ol type=\"$type\"|ul)>\s*</li>#", "<$1>", $list); return $list;@@ -1649,7 +1683,7 @@ $find = array( "#\[(b|u|i|s|url|email|color|img)\](.*?)\[/\\1\]#is",- "#\[img=([0-9]{1,3})x([0-9]{1,3})\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is",+ "#\[img=([1-9][0-9]*)x([1-9][0-9]*)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", "#\[url=([a-z]+?://)([^\r\n\"<]+?)\](.+?)\[/url\]#si", "#\[url=([^\r\n\"<&\(\)]+?)\](.+?)\[/url\]#si", );
Vulnerability Existed: yes
TRUE POSITIVE
Code Injection - CWE-95 - inc/class_parser.php lines 694, 855, 893, 917, 1006, 1030, 1145, 1289
Old Code:
```
$text = "<span style=\"font-size: {$size}pt;\">".str_replace("\'", "'", $text)."</span>";
return $text;
```
New Code:
```
$text = str_replace("\'", "'", $text);
eval("\$mycode_size = \"".$templates->get("mycode_size_int", 1, 0)."\";");
return $mycode_size;
```
Explanation:
Multiple instances of `eval()` have been introduced throughout the file (lines 694, 855, 893, 917, 1006, 1030, 1145, 1289). While these specifically use `$templates->get()` which appears to be a template retrieval function, the use of `eval()` is inherently dangerous. If the template system doesn't properly sanitize or escape variables within the template string, this creates a code injection vulnerability. An attacker who can control template content could inject arbitrary PHP code. The old approach of direct string concatenation, while having other potential issues, avoided the arbitrary code execution risk from `eval()`.
---
Vulnerability Existed: yes
TRUE POSITIVE
Code Injection - CWE-95 - inc/class_parser.php line 673
Old Code:
```
"#(on)([a-z]+\s?=)#i",
```
New Code:
```
"#([\s\"']on)([a-z]+\s*=)#i",
```
Explanation:
This change weakens the XSS filter. The old regex required `on` to start immediately (after `>`, `^`, `\r`, or `\n`), but the new regex with `[\s\"']on` allows matching `on` preceded by whitespace or quotes. This is actually a security improvement, not a vulnerability - it catches more event handler bypass attempts like `<div on click=`, but the change itself represents better security rather than introducing a vulnerability.
---
Vulnerability Existed: not sure
Regular Expression Denial of Service (ReDoS) - CWE-1333 - inc/class_parser.php lines 484-490
Old Code:
```
"#\[img=([0-9]{1,3})x([0-9]{1,3})\]#is"
```
New Code:
```
"#\[img=([1-9][0-9]*)x([1-9][0-9]*)\]#is"
```
Explanation:
The regex change from `[0-9]{1,3}` to `[1-9][0-9]*` modifies the matching pattern. The new pattern prevents leading zeros and allows unlimited length numbers. While `[1-9][0-9]*` is more permissive in terms of length, it's less likely to cause ReDoS since it's a simpler pattern. This appears to be an improvement that disallows invalid image dimensions (like "001x002") while allowing reasonable values. Not a security vulnerability - likely a validation improvement.
--- cache/mybb_mybb_1807/inc/class_session.php 2025-12-06 11:32:55.198126756 +0000+++ cache/mybb_mybb_1808/inc/class_session.php 2025-12-06 11:32:55.970176609 +0000@@ -144,7 +144,7 @@ } // Check the password if we're not using a session- if(empty($loginkey) || $loginkey != $mybb->user['loginkey'] || !$mybb->user['uid'])+ if(empty($loginkey) || $loginkey !== $mybb->user['loginkey'] || !$mybb->user['uid']) { unset($mybb->user); $this->uid = 0;
Vulnerability Existed: yes TRUE POSITIVE Timing Attack Vulnerability / Insecure Comparison - CWE-208 - inc/class_session.php - Line 147 Old Code: ```php if(empty($loginkey) || $loginkey != $mybb->user['loginkey'] || !$mybb->user['uid']) ``` Fixed Code: ```php if(empty($loginkey) || $loginkey !== $mybb->user['loginkey'] || !$mybb->user['uid']) ``` Explanation: The vulnerability was a timing attack vulnerability caused by using the loose comparison operator `!=` instead of the strict comparison operator `!==` when comparing the session login key. The loose comparison `!=` performs type juggling, which can lead to unexpected behavior with certain input values (e.g., "0" == 0 == false), potentially allowing an attacker to bypass authentication. More critically, loose comparisons have consistent timing characteristics that differ from strict comparisons, potentially enabling timing attacks where an attacker measures response times to infer information about the compared values. The fix changes to `!==` (strict comparison), which is the correct approach for security-sensitive comparisons like authentication credentials. This ensures exact type and value matching without type juggling, and provides more consistent timing behavior that is harder to exploit.
--- cache/mybb_mybb_1807/inc/datahandler.php 2025-12-06 11:32:55.198126756 +0000+++ cache/mybb_mybb_1808/inc/datahandler.php 2025-12-06 11:32:55.970176609 +0000@@ -120,7 +120,7 @@ function get_friendly_errors() { global $lang;-+ // Load the language pack we need if($this->language_file) {
Vulnerability Existed: no No vulnerabilities identified - [File] [Lines] [No old code with security implications] [No fixed code with security implications] Explanation: The diff shows only a whitespace change on line 123 (removal of trailing whitespace after the opening brace). This is a code formatting/style change with no security implications. There are no modifications to logic, input validation, data handling, or any other security-sensitive code paths.
--- cache/mybb_mybb_1807/inc/datahandlers/pm.php 2025-12-06 11:32:55.198126756 +0000+++ cache/mybb_mybb_1808/inc/datahandlers/pm.php 2025-12-06 11:32:55.970176609 +0000@@ -297,7 +297,7 @@ { if(!empty($user['ignorelist']) && strpos(','.$user['ignorelist'].',', ','.$pm['fromid'].',') !== false) {- $this->set_error('recipient_is_ignoring', array($user['username']));+ $this->set_error("recipient_is_ignoring", array(htmlspecialchars_uni($user['username']))); } // Is the recipient only allowing private messages from their buddy list?@@ -309,7 +309,7 @@ // Can the recipient actually receive private messages based on their permissions or user setting? if(($user['receivepms'] == 0 || $recipient_permissions['canusepms'] == 0) && empty($pm['saveasdraft'])) {- $this->set_error("recipient_pms_disabled", array($user['username']));+ $this->set_error("recipient_pms_disabled", array(htmlspecialchars_uni($user['username']))); return false; } }@@ -359,7 +359,7 @@ if($this->admin_override != true) {- $this->set_error("recipient_reached_quota", array($user['username']));+ $this->set_error("recipient_reached_quota", array(htmlspecialchars_uni($user['username']))); } } @@ -395,7 +395,7 @@ $pm = &$this->data; // Check if post flooding is enabled within MyBB or if the admin override option is specified.- if($mybb->settings['pmfloodsecs'] > 0 && $pm['fromid'] != 0 && $this->admin_override == false)+ if($mybb->settings['pmfloodsecs'] > 0 && $pm['fromid'] != 0 && $this->admin_override == false && !is_moderator(0, '', $pm['fromid'])) { // Fetch the senders profile data. $sender = get_user($pm['fromid']);@@ -405,7 +405,7 @@ $sender['lastpm'] = $db->fetch_field($query, "dateline"); // A little bit of calculation magic and moderator status checking.- if(TIME_NOW-$sender['lastpm'] <= $mybb->settings['pmfloodsecs'] && !is_moderator("", "", $pm['fromid']))+ if(TIME_NOW-$sender['lastpm'] <= $mybb->settings['pmfloodsecs']) { // Oops, user has been flooding - throw back error message. $time_to_wait = ($mybb->settings['pmfloodsecs'] - (TIME_NOW-$sender['lastpm'])) + 1;
Now I'll provide the security analysis of the code diff:
---
## Vulnerability Analysis
### Vulnerability 1: Cross-Site Scripting (XSS) Prevention
**Vulnerability Existed: yes**
TRUE POSITIVE
**Improper Output Encoding - CWE-79** - `inc/datahandlers/pm.php` Lines 300, 312, 362
**Old Code:**
```php
$this->set_error('recipient_is_ignoring', array($user['username']));
$this->set_error("recipient_pms_disabled", array($user['username']));
$this->set_error("recipient_reached_quota", array($user['username']));
```
**Fixed Code:**
```php
$this->set_error("recipient_is_ignoring", array(htmlspecialchars_uni($user['username'])));
$this->set_error("recipient_pms_disabled", array(htmlspecialchars_uni($user['username'])));
$this->set_error("recipient_reached_quota", array(htmlspecialchars_uni($user['username'])));
```
**Explanation:**
The `$user['username']` variable is passed directly to error messages without HTML encoding. If a username contains special characters or HTML/JavaScript code, it could be reflected in the error message and executed in the user's browser. The fix applies `htmlspecialchars_uni()` to properly encode the username, preventing XSS attacks. This is a legitimate security fix.
---
### Vulnerability 2: Access Control / Authorization Bypass
**Vulnerability Existed: yes**
FALSE POSITIVE
**Improper Access Control - CWE-269** - `inc/datahandlers/pm.php` Lines 398, 408
**Old Code:**
```php
if($mybb->settings['pmfloodsecs'] > 0 && $pm['fromid'] != 0 && $this->admin_override == false)
{
// ... fetch sender data ...
if(TIME_NOW-$sender['lastpm'] <= $mybb->settings['pmfloodsecs'] && !is_moderator("", "", $pm['fromid']))
{
// throw back error message
}
}
```
**Fixed Code:**
```php
if($mybb->settings['pmfloodsecs'] > 0 && $pm['fromid'] != 0 && $this->admin_override == false && !is_moderator(0, '', $pm['fromid']))
{
// ... fetch sender data ...
if(TIME_NOW-$sender['lastpm'] <= $mybb->settings['pmfloodsecs'])
{
// throw back error message
}
}
```
**Explanation:**
The original code had a logic flaw in flood protection bypass detection. Moderators could bypass the flood check because the `is_moderator()` check was only performed inside the inner condition. By moving the moderator check to the outer condition (line 398), the code now prevents moderators from even entering the flood check logic. Additionally, removing the redundant moderator check from the inner condition (line 408) simplifies the logic since moderators are already excluded at the outer level. This fixes an authorization bypass where moderators could potentially exploit relaxed flood restrictions.
---
**Summary:**
- **2 vulnerabilities fixed**: XSS prevention (CWE-79) and access control bypass (CWE-269)
- Both fixes are appropriate security hardening measures
--- cache/mybb_mybb_1807/inc/datahandlers/post.php 2025-12-06 11:32:55.198126756 +0000+++ cache/mybb_mybb_1808/inc/datahandlers/post.php 2025-12-06 11:32:55.970176609 +0000@@ -878,7 +878,7 @@ // Perform any selected moderation tools. $ismod = is_moderator($post['fid'], "", $post['uid']);- if($ismod)+ if($ismod && isset($post['modoptions'])) { $lang->load($this->language_file, true); @@ -886,41 +886,31 @@ $modlogdata['fid'] = $thread['fid']; $modlogdata['tid'] = $thread['tid']; - if(!isset($modoptions['closethread']))- {- $modoptions['closethread'] = $closed;- }- $modoptions_update = array(); // Close the thread.- if($modoptions['closethread'] == 1 && $thread['closed'] != 1)+ if(!empty($modoptions['closethread']) && $thread['closed'] != 1) {- $modoptions_update['closed'] = $closed = 0;+ $modoptions_update['closed'] = $closed = 1; log_moderator_action($modlogdata, $lang->thread_closed); } // Open the thread.- if($modoptions['closethread'] != 1 && $thread['closed'] == 1)+ if(empty($modoptions['closethread']) && $thread['closed'] == 1) {- $modoptions_update['closed'] = $closed = 1;+ $modoptions_update['closed'] = $closed = 0; log_moderator_action($modlogdata, $lang->thread_opened); } - if(!isset($modoptions['stickthread']))- {- $modoptions['stickthread'] = $thread['sticky'];- }- // Stick the thread.- if($modoptions['stickthread'] == 1 && $thread['sticky'] != 1)+ if(!empty($modoptions['stickthread']) && $thread['sticky'] != 1) { $modoptions_update['sticky'] = 1; log_moderator_action($modlogdata, $lang->thread_stuck); } // Unstick the thread.- if($modoptions['stickthread'] != 1 && $thread['sticky'])+ if(empty($modoptions['stickthread']) && $thread['sticky'] == 1) { $modoptions_update['sticky'] = 0; log_moderator_action($modlogdata, $lang->thread_unstuck);@@ -1527,7 +1517,7 @@ } // Perform any selected moderation tools.- if(is_moderator($thread['fid'], "", $thread['uid']) && is_array($thread['modoptions']))+ if(is_moderator($thread['fid'], "", $thread['uid']) && isset($thread['modoptions'])) { $lang->load($this->language_file, true);
```
Vulnerability Existed: yes
TRUE POSITIVE
Improper Input Validation - CWE-20 - inc/datahandlers/post.php - Lines 881-889
Old Code:
if($ismod)
{
$lang->load($this->language_file, true);
$modlogdata['fid'] = $thread['fid'];
$modlogdata['tid'] = $thread['tid'];
if(!isset($modoptions['closethread']))
{
$modoptions['closethread'] = $closed;
}
Fixed Code:
if($ismod && isset($post['modoptions']))
{
$lang->load($this->language_file, true);
$modlogdata['fid'] = $thread['fid'];
$modlogdata['tid'] = $thread['tid'];
$modoptions_update = array();
Explanation:
The vulnerability existed due to use of the `$modoptions` variable without checking if it was set. The old code attempted to set default values for unset keys (`$modoptions['closethread']`, `$modoptions['stickthread']`), but this approach is fragile. The fix adds an explicit `isset($post['modoptions'])` check before entering the moderation block, preventing undefined variable access and potential notice-level errors. Additionally, the fix changes from equality checks (`== 1`, `!= 1`) to safer empty() checks, reducing the risk of type juggling issues.
```
```
Vulnerability Existed: yes
TRUE POSITIVE
Logic Error / Type Juggling - CWE-20 - inc/datahandlers/post.php - Lines 895-908
Old Code:
if($modoptions['closethread'] == 1 && $thread['closed'] != 1)
{
$modoptions_update['closed'] = $closed = 0;
log_moderator_action($modlogdata, $lang->thread_closed);
}
if($modoptions['closethread'] != 1 && $thread['closed'] == 1)
{
$modoptions_update['closed'] = $closed = 1;
log_moderator_action($modlogdata, $lang->thread_opened);
}
Fixed Code:
if(!empty($modoptions['closethread']) && $thread['closed'] != 1)
{
$modoptions_update['closed'] = $closed = 1;
log_moderator_action($modlogdata, $lang->thread_closed);
}
if(empty($modoptions['closethread']) && $thread['closed'] == 1)
{
$modoptions_update['closed'] = $closed = 0;
log_moderator_action($modlogdata, $lang->thread_opened);
}
Explanation:
The old code had multiple issues: (1) Using loose comparison `== 1` is prone to type juggling vulnerabilities where non-boolean values could be unexpectedly coerced, (2) The logic for setting `$closed` was inverted - when closing a thread, it should set `closed = 1`, not `0`. The fix uses safer `!empty()` checks which avoid type juggling issues and corrects the logic to properly set `closed = 1` when the thread should be closed and `closed = 0` when opened.
```
```
Vulnerability Existed: yes
FALSE POSITIVE
Logic Error - CWE-20 - inc/datahandlers/post.php - Lines 917-920
Old Code:
if($modoptions['stickthread'] != 1 && $thread['sticky'])
{
$modoptions_update['sticky'] = 0;
log_moderator_action($modlogdata, $lang->thread_unstuck);
}
Fixed Code:
if(empty($modoptions['stickthread']) && $thread['sticky'] == 1)
{
$modoptions_update['sticky'] = 0;
log_moderator_action($modlogdata, $lang->thread_unstuck);
}
Explanation:
The old code used loose comparison `$thread['sticky']` without explicit comparison to 1, relying on type juggling. This could cause unexpected behavior if `$thread['sticky']` contains a truthy but non-1 value. The fix uses explicit comparison `$thread['sticky'] == 1` combined with `empty()` checks, making the intent clearer and reducing type juggling risks.
```
```
Vulnerability Existed: yes
FALSE POSITIVE
Improper Input Validation - CWE-20 - inc/datahandlers/post.php - Line 1520
Old Code:
if(is_moderator($thread['fid'], "", $thread['uid']) && is_array($thread['modoptions']))
Fixed Code:
if(is_moderator($thread['fid'], "", $thread['uid']) && isset($thread['modoptions']))
Explanation:
The old code uses `is_array()` to check if `$thread['modoptions']` exists, but this is overly restrictive and could fail silently if the variable is set but not an array. The fix changes to `isset()`, which is the proper way to check for variable existence. This is more defensive and allows the code to handle cases where the variable exists but might not be strictly an array, while still preventing undefined variable notices.
```
--- cache/mybb_mybb_1807/inc/datahandlers/user.php 2025-12-06 11:32:55.198126756 +0000+++ cache/mybb_mybb_1808/inc/datahandlers/user.php 2025-12-06 11:32:55.970176609 +0000@@ -303,20 +303,12 @@ { $website = &$this->data['website']; - if(empty($website) || my_strtolower($website) == 'http://' || my_strtolower($website) == 'https://')+ if(!empty($website) && !my_validate_url($website)) {- $website = '';- return true;- }-- // Does the website start with http(s)://?- if(my_strtolower(substr($website, 0, 4)) != "http")- {- // Website does not start with http://, let's see if the user forgot.- $website = "http://".$website;+ $website = 'http://'.$website; } - if(!filter_var($website, FILTER_VALIDATE_URL))+ if(!empty($website) && !my_validate_url($website)) { $this->set_error('invalid_website'); return false;@@ -921,7 +913,7 @@ } /**- * Verifies if the user timezone is valid. + * Verifies if the user timezone is valid. * If the timezone is invalid, the board default is used. * * @return boolean True when timezone was valid, false otherwise@@ -1055,6 +1047,10 @@ { $this->verify_style(); }+ if($this->method == "insert" || array_key_exists('signature', $user))+ {+ $this->verify_signature();+ } $plugins->run_hooks("datahandler_user_validate", $this); @@ -1378,7 +1374,7 @@ } if(isset($user['away'])) {- $this->user_update_data['away'] = $user['away']['away'];+ $this->user_update_data['away'] = (int)$user['away']['away']; $this->user_update_data['awaydate'] = $db->escape_string($user['away']['date']); $this->user_update_data['returndate'] = $db->escape_string($user['away']['returndate']); $this->user_update_data['awayreason'] = $db->escape_string($user['away']['awayreason']);@@ -1606,7 +1602,7 @@ if($delete_uids != false) { $this->delete_uids = array_map('intval', (array)$delete_uids);- + foreach($this->delete_uids as $key => $uid) { if(!$uid || is_super_admin($uid) || $uid == $mybb->user['uid'])@@ -1615,7 +1611,7 @@ unset($this->delete_uids[$key]); } }- + $this->delete_uids = implode(',', $this->delete_uids); } @@ -1783,4 +1779,74 @@ remove_avatars($uid); } }++ public function verify_signature()+ {+ global $mybb, $parser;++ if(!isset($parser))+ {+ require_once MYBB_ROOT."inc/class_parser.php";+ $parser = new postParser;+ }++ $parser_options = array(+ 'allow_html' => $mybb->settings['sightml'],+ 'filter_badwords' => 1,+ 'allow_mycode' => $mybb->settings['sigmycode'],+ 'allow_smilies' => $mybb->settings['sigsmilies'],+ 'allow_imgcode' => $mybb->settings['sigimgcode'],+ "filter_badwords" => 1+ );++ $parsed_sig = $parser->parse_message($this->data['signature'], $parser_options);++ if((($mybb->settings['sigimgcode'] == 0 && $mybb->settings['sigsmilies'] != 1) &&+ substr_count($parsed_sig, "<img") > 0) ||+ (($mybb->settings['sigimgcode'] == 1 || $mybb->settings['sigsmilies'] == 1) &&+ substr_count($parsed_sig, "<img") > $mybb->settings['maxsigimages'])+ )+ {+ $imgsallowed = 0;+ + if($mybb->settings['sigimgcode'] == 1)+ {+ $imgsallowed = $mybb->settings['maxsigimages'];+ }++ $this->set_error('too_many_sig_images2', array($imgsallowed));+ }++ if($mybb->settings['sigcountmycode'] == 0)+ {+ $parsed_sig = $parser->text_parse_message($this->data['signature']);+ }+ else+ {+ $parsed_sig = $this->data['signature'];+ }++ $parsed_sig = preg_replace("#\s#", "", $parsed_sig);+ $sig_length = my_strlen($parsed_sig);++ if($sig_length > $mybb->settings['siglength'])+ {+ $this->set_error('sig_too_long', array($mybb->settings['siglength']));++ if($sig_length - $mybb->settings['siglength'] > 1)+ {+ $this->set_error('sig_remove_chars_plural', array($sig_length-$mybb->settings['siglength']));+ }+ else+ {+ $this->set_error('sig_remove_chars_singular');+ }+ }++ if(count($this->get_errors()) > 0)+ {+ return false;+ }+ return true;+ } }
### Summary This diff represents **security improvements** addressing three areas: 1. **Website URL validation refactored** to use a dedicated validation function instead of filter_var 2. **Signature verification added** - a completely new validation gate preventing previous unvalidated user content 3. **Type casting hardened** for database operations The most significant security fix is the addition of signature verification, which prevents users from injecting malicious content into signatures. The website validation refactor improves robustness but maintains some logical duplication that could be cleaned up.
--- cache/mybb_mybb_1807/inc/db_sqlite.php 2025-12-06 11:32:55.214127789 +0000+++ cache/mybb_mybb_1808/inc/db_sqlite.php 2025-12-06 11:32:55.974176867 +0000@@ -32,6 +32,13 @@ public $type; /** + * PDOStatement objects of performed queries. + * + * @var array + */ + public $query_objects = array(); + + /** * A count of the number of queries. * * @var int @@ -209,6 +216,8 @@ } } + $this->query_objects[] = $query; + if($this->error_number($query) > 0 && !$hide_errors) { $this->error($string, $query); @@ -331,6 +340,25 @@ } /** + * Closes cursors of registered queries. + * + */ + function close_cursors() + { + $result = true; + + foreach($this->query_objects as $query) + { + if(!$query->closeCursor()) + { + $result = false; + } + } + + return $result; + } + + /** * Return the number of rows resulting from a query. * * @param PDOStatement $query The query data.
I'll analyze this code diff for security vulnerabilities. **Vulnerability Existed: no** The diff shows the addition of query cursor management functionality in a MyBB SQLite database class. This is a **resource management improvement**, not a security fix addressing an existing vulnerability. **Analysis:** The changes introduce: 1. A new `$query_objects` array property to track PDOStatement objects 2. Storage of query objects during execution: `$this->query_objects[] = $query;` 3. A new `close_cursors()` method that calls `closeCursor()` on all tracked queries **Why this is NOT a security vulnerability fix:** - **No vulnerability being patched**: The code is adding resource cleanup capability, not fixing a security flaw - **No injection risks**: The changes don't involve user input, SQL construction, or dangerous operations - **No access control changes**: No modifications to authentication, authorization, or permission checking - **No cryptographic issues**: No changes to data protection or encryption - **Resource management improvement**: This is a performance/stability enhancement to prevent "PDO cursor limit exceeded" errors by properly closing statement cursors **What the code actually does:** This appears to address a resource exhaustion issue where PDO cursors weren't being explicitly closed, potentially causing database connection limits to be exceeded. The fix ensures proper cleanup of database resources, which is a best practice but not a security vulnerability remediation. **Conclusion:** This is a maintenance/stability improvement rather than a security fix. There is no vulnerability being corrected here.
--- cache/mybb_mybb_1807/inc/functions.php 2025-12-06 11:32:55.214127789 +0000+++ cache/mybb_mybb_1808/inc/functions.php 2025-12-06 11:32:55.974176867 +0000@@ -598,7 +598,7 @@ function verify_post_check($code, $silent=false) { global $lang;- if(generate_post_check() != $code)+ if(generate_post_check() !== $code) { if($silent == true) {@@ -865,7 +865,7 @@ if($mybb->user['uid']) {- $lang->error_nopermission_user_username = $lang->sprintf($lang->error_nopermission_user_username, $mybb->user['username']);+ $lang->error_nopermission_user_username = $lang->sprintf($lang->error_nopermission_user_username, htmlspecialchars_uni($mybb->user['username'])); eval("\$errorpage = \"".$templates->get("error_nopermission_loggedin")."\";"); } else@@ -966,7 +966,7 @@ run_shutdown(); - if(my_substr($url, 0, 7) !== 'http://' && my_substr($url, 0, 8) !== 'https://' && my_substr($url, 0, 1) !== '/')+ if(!my_validate_url($url, true)) { header("Location: {$mybb->settings['bburl']}/{$url}"); }@@ -1209,7 +1209,7 @@ * Fetch the usergroup permissions for a specific group or series of groups combined * * @param int|string $gid A list of groups (Can be a single integer, or a list of groups separated by a comma)- * @return array Array of permissions generated for the groups+ * @return array Array of permissions generated for the groups, containing also a list of comma-separated checked groups under 'all_usergroups' index */ function usergroup_permissions($gid=0) {@@ -1224,14 +1224,16 @@ if(count($groups) == 1) {+ $groupscache[$gid]['all_usergroups'] = $gid; return $groupscache[$gid]; }- + $usergroup = array();+ $usergroup['all_usergroups'] = $gid; foreach($groups as $gid) {- if(trim($gid) == "" || !$groupscache[$gid])+ if(trim($gid) == "" || empty($groupscache[$gid])) { continue; }@@ -1714,14 +1716,19 @@ { foreach($modcache as $modusers) {- if(isset($modusers['users'][$uid]) && $modusers['users'][$uid]['mid'])+ if(isset($modusers['users'][$uid]) && $modusers['users'][$uid]['mid'] && (!$action || !empty($modusers['users'][$uid][$action]))) { return true; }- elseif(isset($user_perms['gid']) && isset($modusers['usergroups'][$user_perms['gid']]))++ $groups = explode(',', $user_perms['all_usergroups']);++ foreach($groups as $group) {- // Moderating usergroup- return true;+ if(trim($group) != '' && isset($modusers['usergroups'][$group]) && (!$action || !empty($modusers['usergroups'][$group][$action])))+ {+ return true;+ } } } }@@ -1794,7 +1801,14 @@ eval("\$iconlist .= \"".$templates->get("posticons_icon")."\";"); } - eval("\$posticons = \"".$templates->get("posticons")."\";");+ if(!empty($iconlist))+ {+ eval("\$posticons = \"".$templates->get("posticons")."\";");+ }+ else+ {+ $posticons = '';+ } return $posticons; }@@ -2145,7 +2159,7 @@ { mb_internal_encoding($mbIntEnc); }- + return $out; } @@ -2165,27 +2179,27 @@ { return 'N;'; }- + if(is_bool($value)) { return 'b:'.(int)$value.';'; }- + if(is_int($value)) { return 'i:'.$value.';'; }- + if(is_float($value)) { return 'd:'.str_replace(',', '.', $value).';'; }- + if(is_string($value)) { return 's:'.strlen($value).':"'.$value.'";'; }- + if(is_array($value)) { $out = '';@@ -2193,7 +2207,7 @@ { $out .= _safe_serialize($k) . _safe_serialize($v); }- + return 'a:'.count($value).':{'.$out.'}'; } @@ -2216,13 +2230,13 @@ $mbIntEnc = mb_internal_encoding(); mb_internal_encoding('ASCII'); }- + $out = _safe_serialize($value); if(isset($mbIntEnc)) { mb_internal_encoding($mbIntEnc); }- + return $out; } @@ -2414,7 +2428,7 @@ $query = $db->simple_select("users", "uid, username", "", array('order_by' => 'regdate', 'order_dir' => 'DESC', 'limit' => 1)); $lastmember = $db->fetch_array($query); $new_stats['lastuid'] = $lastmember['uid'];- $new_stats['lastusername'] = $lastmember['username'];+ $new_stats['lastusername'] = $lastmember['username'] = htmlspecialchars_uni($lastmember['username']); } if(!empty($new_stats))@@ -2975,7 +2989,7 @@ { $str[] = $set[my_rand(0, 61)]; }- + // Make sure they're in random order and convert them to a string shuffle($str); @@ -3028,7 +3042,7 @@ */ function format_avatar($avatar, $dimensions = '', $max_dimensions = '') {- global $mybb;+ global $mybb, $theme; static $avatars; if(!isset($avatars))@@ -3039,7 +3053,12 @@ if(!$avatar) { // Default avatar- $avatar = $mybb->settings['useravatar'];+ if(defined('IN_ADMINCP'))+ {+ $theme['imgdir'] = '../images';+ }++ $avatar = str_replace('{theme}', $theme['imgdir'], $mybb->settings['useravatar']); $dimensions = $mybb->settings['useravatardims']; } @@ -3214,12 +3233,6 @@ $emoticons_enabled = "false"; if($smilies) {- if($mybb->settings['smilieinserter'] && $mybb->settings['smilieinsertercols'] && $mybb->settings['smilieinsertertot'])- {- $emoticon = ",emoticon";- }- $emoticons_enabled = "true";- if(!$smiliecache) { if(!isset($smilie_cache) || !is_array($smilie_cache))@@ -3233,6 +3246,12 @@ } } + if($mybb->settings['smilieinserter'] && $mybb->settings['smilieinsertercols'] && $mybb->settings['smilieinsertertot'] && !empty($smiliecache))+ {+ $emoticon = ",emoticon";+ }+ $emoticons_enabled = "true";+ unset($smilie); if(is_array($smiliecache))@@ -3256,7 +3275,7 @@ if(!$mybb->settings['smilieinserter'] || !$mybb->settings['smilieinsertercols'] || !$mybb->settings['smilieinsertertot'] || !$smilie['showclickable']) {- $hiddensmilies .= '"'.$find.'": "'.$image.'",'; + $hiddensmilies .= '"'.$find.'": "'.$image.'",'; } elseif($i < $mybb->settings['smilieinsertertot']) {@@ -3389,7 +3408,7 @@ eval("\$getmore = \"".$templates->get("smilieinsert_getmore")."\";"); } - $smilies = "";+ $smilies = ''; $counter = 0; $i = 0; @@ -3398,15 +3417,10 @@ { if($i < $mybb->settings['smilieinsertertot'] && $smilie['showclickable'] != 0) {- if($counter == 0)- {- $smilies .= "<tr>\n";- }- $smilie['image'] = str_replace("{theme}", $theme['imgdir'], $smilie['image']); $smilie['image'] = htmlspecialchars_uni($mybb->get_asset_url($smilie['image'])); $smilie['name'] = htmlspecialchars_uni($smilie['name']);- + // Only show the first text to replace in the box $temp = explode("\n", $smilie['find']); // assign to temporary variable for php 5.3 compatibility $smilie['find'] = $temp[0];@@ -3416,14 +3430,15 @@ $onclick = " onclick=\"MyBBEditor.insertText(' $find ');\""; $extra_class = ' smilie_pointer'; eval('$smilie = "'.$templates->get('smilie', 1, 0).'";');- eval("\$smilies .= \"".$templates->get("smilieinsert_smilie")."\";");+ eval("\$smilie_icons .= \"".$templates->get("smilieinsert_smilie")."\";"); ++$i; ++$counter; if($counter == $mybb->settings['smilieinsertercols']) { $counter = 0;- $smilies .= "</tr>\n";+ eval("\$smilies .= \"".$templates->get("smilieinsert_row")."\";");+ $smilie_icons = ''; } } }@@ -3431,7 +3446,7 @@ if($counter != 0) { $colspan = $mybb->settings['smilieinsertercols'] - $counter;- $smilies .= "<td colspan=\"{$colspan}\"> </td>\n</tr>\n";+ eval("\$smilies .= \"".$templates->get("smilieinsert_row_empty")."\";"); } eval("\$clickablesmilies = \"".$templates->get("smilieinsert")."\";");@@ -3644,7 +3659,7 @@ $default_selected = array(); $selected_pid = (int)$selected_pid;- + if($selected_pid == 0) { $default_selected['all'] = ' selected="selected"';@@ -3800,7 +3815,7 @@ { $reputation_class = "reputation_neutral"; }- + $reputation = my_number_format($reputation); if($uid != 0)@@ -4136,9 +4151,9 @@ $unviewable[] = $forum['fid']; } }- + $unviewableforums = implode(',', $unviewable);- + return $unviewableforums; } @@ -4885,7 +4900,7 @@ { $location = htmlspecialchars_uni($_ENV['PATH_INFO']); }- + if($quick) { return $location;@@ -4997,13 +5012,6 @@ if(is_array($tcache[$tid])) {- // Figure out what groups this user is in- if(isset($mybb->user['additionalgroups']))- {- $in_groups = explode(",", $mybb->user['additionalgroups']);- }- $in_groups[] = $mybb->user['usergroup'];- foreach($tcache[$tid] as $theme) { $sel = "";@@ -5701,6 +5709,7 @@ */ function get_event_poster($event) {+ $event['username'] = htmlspecialchars_uni($event['username']); $event['username'] = format_name($event['username'], $event['usergroup'], $event['displaygroup']); $event_poster = build_profile_link($event['username'], $event['author']); return $event_poster;@@ -5717,7 +5726,7 @@ global $mybb; $event_date = explode("-", $event['date']);- $event_date = mktime(0, 0, 0, $event_date[1], $event_date[0], $event_date[2]);+ $event_date = gmmktime(0, 0, 0, $event_date[1], $event_date[0], $event_date[2]); $event_date = my_date($mybb->settings['dateformat'], $event_date); return $event_date;@@ -6171,7 +6180,7 @@ } } }- + $inactiveforums = implode(",", $inactive); return $inactiveforums;@@ -6676,6 +6685,8 @@ "6.5" => $lang->timezone_gmt_650, "7" => $lang->timezone_gmt_700, "8" => $lang->timezone_gmt_800,+ "8.5" => $lang->timezone_gmt_850,+ "8.75" => $lang->timezone_gmt_875, "9" => $lang->timezone_gmt_900, "9.5" => $lang->timezone_gmt_950, "10" => $lang->timezone_gmt_1000,@@ -6754,7 +6765,48 @@ */ function fetch_remote_file($url, $post_data=array(), $max_redirects=20) {- global $mybb;+ global $mybb, $config;++ $url_components = @parse_url($url);++ if(+ !$url_components ||+ empty($url_components['host']) ||+ (!empty($url_components['scheme']) && !in_array($url_components['scheme'], array('http', 'https'))) ||+ (!empty($url_components['port']) && !in_array($url_components['port'], array(80, 8080, 443))) ||+ (!empty($config['disallowed_remote_hosts']) && in_array($url_components['host'], $config['disallowed_remote_hosts']))+ )+ {+ return false;+ }++ if(!empty($config['disallowed_remote_addresses']))+ {+ $addresses = gethostbynamel($url_components['host']);+ if($addresses)+ {+ foreach($config['disallowed_remote_addresses'] as $disallowed_address)+ {+ $ip_range = fetch_ip_range($disallowed_address);+ foreach($addresses as $address)+ {+ $packed_address = my_inet_pton($address);++ if(is_array($ip_range))+ {+ if(strcmp($ip_range[0], $packed_address) <= 0 && strcmp($ip_range[1], $packed_address) >= 0)+ {+ return false;+ }+ }+ elseif($address == $disallowed_address)+ {+ return false;+ }+ }+ }+ }+ } $post_body = ''; if(!empty($post_data))@@ -6823,36 +6875,31 @@ } else if(function_exists("fsockopen")) {- $url = @parse_url($url);- if(!$url['host'])+ if(!isset($url_components['port'])) {- return false;+ $url_components['port'] = 80; }- if(!isset($url['port']))+ if(!isset($url_components['path'])) {- $url['port'] = 80;+ $url_components['path'] = "/"; }- if(!isset($url['path']))+ if(isset($url_components['query'])) {- $url['path'] = "/";- }- if(isset($url['query']))- {- $url['path'] .= "?{$url['query']}";+ $url_components['path'] .= "?{$url_components['query']}"; } $scheme = ''; - if($url['scheme'] == 'https')+ if($url_components['scheme'] == 'https') { $scheme = 'ssl://';- if($url['port'] == 80)+ if($url_components['port'] == 80) {- $url['port'] = 443;+ $url_components['port'] = 443; } } - $fp = @fsockopen($scheme.$url['host'], $url['port'], $error_no, $error, 10);+ $fp = @fsockopen($scheme.$url_components['host'], $url_components['port'], $error_no, $error, 10); @stream_set_timeout($fp, 10); if(!$fp) {@@ -6861,16 +6908,16 @@ $headers = array(); if(!empty($post_body)) {- $headers[] = "POST {$url['path']} HTTP/1.0";+ $headers[] = "POST {$url_components['path']} HTTP/1.0"; $headers[] = "Content-Length: ".strlen($post_body); $headers[] = "Content-Type: application/x-www-form-urlencoded"; } else {- $headers[] = "GET {$url['path']} HTTP/1.0";+ $headers[] = "GET {$url_components['path']} HTTP/1.0"; } - $headers[] = "Host: {$url['host']}";+ $headers[] = "Host: {$url_components['host']}"; $headers[] = "Connection: Close"; $headers[] = ''; @@ -6968,7 +7015,7 @@ function is_member($groups, $user = false) { global $mybb;- + if(empty($groups)) { return array();@@ -8413,3 +8460,22 @@ return $success; }++/**+ * Validate an url+ *+ * @param string $url The url to validate.+ * @param bool $relative_path Whether or not the url could be a relative path.+ *+ * @return bool Whether this is a valid url.+ */+function my_validate_url($url, $relative_path=false)+{+ if($relative_path && my_substr($url, 0, 1) == '/' || preg_match('_^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]-*)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]-*)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$_iuS', $url))+ {+ return true;+ }++ return false;+}+
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - inc/functions.php lines 868
Old Code:
```php
$lang->error_nopermission_user_username = $lang->sprintf($lang->error_nopermission_user_username, $mybb->user['username']);
```
Fixed Code:
```php
$lang->error_nopermission_user_username = $lang->sprintf($lang->error_nopermission_user_username, htmlspecialchars_uni($mybb->user['username']));
```
Explanation:
User-controlled data from `$mybb->user['username']` was passed directly to `sprintf()` and subsequently used in an `eval()` statement (line 869) without HTML escaping. This allows attackers with control over their username to inject arbitrary PHP code or HTML/JavaScript into the page. The fix properly escapes the username using `htmlspecialchars_uni()` before using it in the template evaluation.
---
Vulnerability Existed: yes
FALSE POSITIVE
Improper Input Validation - CWE-20 - inc/functions.php lines 969
Old Code:
```php
if(my_substr($url, 0, 7) !== 'http://' && my_substr($url, 0, 8) !== 'https://' && my_substr($url, 0, 1) !== '/')
```
Fixed Code:
```php
if(!my_validate_url($url, true))
```
Explanation:
The original code attempted URL validation through simple string prefix checking, which is insufficient and potentially bypassable. The fix delegates to a dedicated `my_validate_url()` function that implements proper URL validation including scheme verification, SSRF prevention checks against private IP ranges, and disallowed host/address configuration support.
---
Vulnerability Existed: yes
TRUE POSITIVE
Server-Side Request Forgery (SSRF) - CWE-918 - inc/functions.php lines 6754-6815
Old Code:
```php
function fetch_remote_file($url, $post_data=array(), $max_redirects=20)
{
global $mybb;
// ... no validation of URL before making request
```
Fixed Code:
```php
function fetch_remote_file($url, $post_data=array(), $max_redirects=20)
{
global $mybb, $config;
$url_components = @parse_url($url);
if(
!$url_components ||
empty($url_components['host']) ||
(!empty($url_components['scheme']) && !in_array($url_components['scheme'], array('http', 'https'))) ||
(!empty($url_components['port']) && !in_array($url_components['port'], array(80, 8080, 443))) ||
(!empty($config['disallowed_remote_hosts']) && in_array($url_components['host'], $config['disallowed_remote_hosts']))
)
{
return false;
}
if(!empty($config['disallowed_remote_addresses']))
{
$addresses = gethostbynamel($url_components['host']);
// ... IP range validation against disallowed addresses
}
```
Explanation:
The original function accepted arbitrary URLs without validation, allowing attackers to make requests to internal/private IP addresses (localhost, 127.0.0.1, 192.168.*, etc.) or arbitrary hosts. The fix implements comprehensive SSRF protection by: (1) validating URL scheme is http/https only, (2) validating port is whitelisted (80, 8080, 443), (3) checking against configured disallowed hosts, and (4) performing IP range validation to block private/internal IP addresses.
---
Vulnerability Existed: yes
FALSE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - inc/functions.php line 2431
Old Code:
```php
$new_stats['lastusername'] = $lastmember['username'];
```
Fixed Code:
```php
$new_stats['lastusername'] = $lastmember['username'] = htmlspecialchars_uni($lastmember['username']);
```
Explanation:
Database-retrieved username was used without HTML escaping in templates, allowing stored XSS if usernames contain malicious HTML/JavaScript. The fix escapes the username before storage and use.
---
Vulnerability Existed: yes
TRUE POSITIVE
Access Control Bypass - CWE-639 - inc/functions.php lines 1719-1737
Old Code:
```php
if(isset($modusers['users'][$uid]) && $modusers['users'][$uid]['mid'])
{
return true;
}
elseif(isset($user_perms['gid']) && isset($modusers['usergroups'][$user_perms['gid']]))
{
// Moderating usergroup
return true;
}
```
Fixed Code:
```php
if(isset($modusers['users'][$uid]) && $modusers['users'][$uid]['mid'] && (!$action || !empty($modusers['users'][$uid][$action])))
{
return true;
}
$groups = explode(',', $user_perms['all_usergroups']);
foreach($groups as $group)
{
if(trim($group) != '' && isset($modusers['usergroups'][$group]) && (!$action || !empty($modusers['usergroups'][$group][$action])))
{
return true;
}
}
```
Explanation:
The original code granted moderation permissions based on a single usergroup (`$user_perms['gid']`), not accounting for users in multiple groups. Additionally, it didn't validate that the user actually had the specific action permission within that group. The fix properly iterates through all user groups (`all_usergroups`) and validates that the requested action is permitted within the group, preventing privilege escalation.
---
Vulnerability Existed: yes
FALSE POSITIVE
Information Disclosure - CWE-200 - inc/functions.php lines 1803-1810
Old Code:
```php
eval("\$posticons = \"".$templates->get("posticons")."\";");
return $posticons;
```
Fixed Code:
```php
if(!empty($iconlist))
{
eval("\$posticons = \"".$templates->get("posticons")."\";");
}
else
{
$posticons = '';
}
return $posticons;
```
Explanation:
When `$iconlist` is empty, the template evaluation still occurs, which may contain conditional rendering logic that leaks information about available features or system state. The fix prevents template evaluation when no icons exist, avoiding potential information leakage.
---
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - inc/functions.php line 5710
Old Code:
```php
$event['username'] = format_name($event['username'], $event['usergroup'], $event['displaygroup']);
```
Fixed Code:
```php
$event['username'] = htmlspecialchars_uni($event['username']);
$event['username'] = format_name($event['username'], $event['usergroup'], $event['displaygroup']);
```
Explanation:
The username from the database was passed directly to `format_name()` without prior escaping. The fix escapes the username before processing to prevent stored XSS attacks.
---
Vulnerability Existed: not sure
Time Zone Handling - CWE-676 - inc/functions.php line 5729
Old Code:
```php
$event_date = mktime(0, 0, 0, $event_date[1], $event_date[0], $event_date[2]);
```
Fixed Code:
```php
$event_date = gmmktime(0, 0, 0, $event_date[1], $event_date[0], $event_date[2]);
```
Explanation:
Changed from `mktime()` to `gmmktime()`. This is not strictly a security vulnerability but a correctness fix. `gmmktime()` returns a Unix timestamp in GMT/UTC, while `mktime()` interprets the time in the system's local timezone. This change may affect how event dates are handled depending on the server's timezone configuration. The fix ensures consistent UTC-based timestamp generation, which is generally safer for distributed systems, but the security impact depends on how this timestamp is subsequently used.
--- cache/mybb_mybb_1807/inc/functions_archive.php 2025-12-06 11:32:55.214127789 +0000+++ cache/mybb_mybb_1808/inc/functions_archive.php 2025-12-06 11:32:55.974176867 +0000@@ -172,7 +172,7 @@ <div class="navigation"><?php echo $nav; ?></div> </div> <div id="footer">-<?php echo $lang->powered_by; ?> <a href="http://www.mybb.com">MyBB</a><?php echo $mybbversion; ?>, © 2002-<?php echo date("Y"); ?> <a href="http://www.mybb.com">MyBB Group</a>+<?php echo $lang->powered_by; ?> <a href="https://mybb.com">MyBB</a><?php echo $mybbversion; ?>, © 2002-<?php echo date("Y"); ?> <a href="https://mybb.com">MyBB Group</a> </div> </body> </html>
Vulnerability Existed: no
HTTPS Upgrade - Not a Vulnerability - inc/functions_archive.php [175]
[Old Code]
<?php echo $lang->powered_by; ?> <a href="http://www.mybb.com">MyBB</a><?php echo $mybbversion; ?>, © 2002-<?php echo date("Y"); ?> <a href="http://www.mybb.com">MyBB Group</a>
[Fixed Code]
<?php echo $lang->powered_by; ?> <a href="https://mybb.com">MyBB</a><?php echo $mybbversion; ?>, © 2002-<?php echo date("Y"); ?> <a href="https://mybb.com">MyBB Group</a>
Explanation:
This change upgrades HTTP links to HTTPS and removes the "www" subdomain. This is a security best practice (HTTPS enforces encrypted communication) rather than a fix for an existing vulnerability in the code itself. The original code did not contain a security vulnerability—it was simply using the less secure HTTP protocol. This is a hardening measure, not a vulnerability fix.
--- cache/mybb_mybb_1807/inc/functions_calendar.php 2025-12-06 11:32:55.214127789 +0000+++ cache/mybb_mybb_1808/inc/functions_calendar.php 2025-12-06 11:32:55.974176867 +0000@@ -152,7 +152,8 @@ } if($link_to_day) {- $day_link = "<a href=\"".get_calendar_link($calendar['cid'], $calendar_year, $calendar_month, $day)."\">{$day}</a>";+ $calendar['link'] = get_calendar_link($calendar['cid'], $calendar_year, $calendar_month, $day);+ eval("\$day_link = \"".$templates->get("calendar_mini_weekrow_day_link")."\";"); } else {@@ -429,9 +430,9 @@ { global $db, $mybb; - // We take in to account timezones here - we add/subtract 12 hours from our GMT time ranges+ // We take in to account timezones here - we either add 14 hours or subtract 12 hours from our GMT time ranges $start -= 12*3600;- $end += 12*3600;+ $end += 14*3600; $visible_where = ''; if($unapproved != 1)
Vulnerability Existed: yes
TRUE POSITIVE
[Code Injection via eval] - [CWE-95] - [inc/functions_calendar.php] [Line 155]
**Old Code:**
```php
$day_link = "<a href=\"".get_calendar_link($calendar['cid'], $calendar_year, $calendar_month, $day)."\">{$day}</a>";
```
**Fixed Code:**
```php
$calendar['link'] = get_calendar_link($calendar['cid'], $calendar_year, $calendar_month, $day);
eval("\$day_link = \"".$templates->get("calendar_mini_weekrow_day_link")."\";");
```
**Explanation:**
This is NOT a security fix—it's a regression that INTRODUCES a critical vulnerability. The original code safely concatenated strings to build an HTML link. The new code uses `eval()` with user-controlled data (`$calendar['link']`), which is embedded into a template string and executed. This allows arbitrary PHP code execution if `$calendar['link']` contains malicious input. While the data comes from `get_calendar_link()` (which may be sanitized), using `eval()` is dangerous and unnecessary here. The proper fix would be to use template variable substitution without `eval()`, such as setting template variables directly and letting the template engine handle escaping.
---
Vulnerability Existed: no
[Timezone Handling Logic Change] - [CWE-Not Applicable] - [inc/functions_calendar.php] [Line 433-435]
**Old Code:**
```php
// We take in to account timezones here - we add/subtract 12 hours from our GMT time ranges
$start -= 12*3600;
$end += 12*3600;
```
**Fixed Code:**
```php
// We take in to account timezones here - we either add 14 hours or subtract 12 hours from our GMT time ranges
$start -= 12*3600;
$end += 14*3600;
```
**Explanation:**
This change is a logic correction, not a security vulnerability fix. It adjusts the timezone offset calculation from symmetric (±12 hours) to asymmetric (−12 hours, +14 hours), which may better account for extreme timezone ranges (UTC-12 to UTC+14). This is a business logic adjustment, not fixing a security issue. No vulnerability exists in either version from a security perspective.
--- cache/mybb_mybb_1807/inc/functions_forumlist.php 2025-12-06 11:32:55.214127789 +0000+++ cache/mybb_mybb_1808/inc/functions_forumlist.php 2025-12-06 11:32:55.974176867 +0000@@ -292,6 +292,7 @@ $lastpost_date = my_date('relative', $lastpost_data['lastpost']); // Set up the last poster, last post thread id, last post subject and format appropriately+ $lastpost_data['lastposter'] = htmlspecialchars_uni($lastpost_data['lastposter']); $lastpost_profilelink = build_profile_link($lastpost_data['lastposter'], $lastpost_data['lastposteruid']); $lastpost_link = get_thread_link($lastpost_data['lastposttid'], 0, "lastpost"); $lastpost_subject = $full_lastpost_subject = $parser->parse_badwords($lastpost_data['lastpostsubject']);
Vulnerability Existed: yes TRUE POSITIVE Cross-Site Scripting (XSS) - CWE-79 - inc/functions_forumlist.php Line 295 Old Code: ``` $lastpost_profilelink = build_profile_link($lastpost_data['lastposter'], $lastpost_data['lastposteruid']); ``` Fixed Code: ``` $lastpost_data['lastposter'] = htmlspecialchars_uni($lastpost_data['lastposter']); $lastpost_profilelink = build_profile_link($lastpost_data['lastposter'], $lastpost_data['lastposteruid']); ``` Explanation: The vulnerability existed because `$lastpost_data['lastposter']` was being passed directly to `build_profile_link()` without HTML encoding. If this value contained user-controlled data (e.g., a username or display name), an attacker could inject malicious HTML/JavaScript that would execute in the browser when the forum list is rendered. The fix applies `htmlspecialchars_uni()` to encode the lastposter value before using it, preventing XSS injection. This is a proper reflected/stored XSS mitigation for displaying user-influenced data in HTML context.
--- cache/mybb_mybb_1807/inc/functions_indicators.php 2025-12-06 11:32:55.214127789 +0000+++ cache/mybb_mybb_1808/inc/functions_indicators.php 2025-12-06 11:32:55.974176867 +0000@@ -58,8 +58,38 @@ { global $cache, $db, $mybb; - $onlyview = $onlyview2 = '';- $permissions = forum_permissions($fid);+ $forums_all = $forums_own = array();+ $forums = explode(',', $fid);+ foreach($forums as $forum)+ {+ $permissions = forum_permissions($forum);+ if(!empty($permissions['canonlyviewownthreads']))+ {+ $forums_own[] = $forum;+ }+ else+ {+ $forums_all[] = $forum;+ }+ }+ if(!empty($forums_own))+ {+ $where = "(fid IN (".implode(',', $forums_own).") AND uid = {$mybb->user['uid']})";+ $where2 = "(t.fid IN (".implode(',', $forums_own).") AND t.uid = {$mybb->user['uid']})";+ }+ if(!empty($forums_all))+ {+ if(isset($where))+ {+ $where = "({$where} OR fid IN (".implode(',', $forums_all)."))";+ $where2 = "({$where2} OR t.fid IN (".implode(',', $forums_all)."))";+ }+ else+ {+ $where = 'fid IN ('.implode(',', $forums_all).')';+ $where2 = 't.fid IN ('.implode(',', $forums_all).')';+ }+ } $cutoff = TIME_NOW-$mybb->settings['threadreadcut']*60*60*24; if(!empty($permissions['canonlyviewownthreads']))@@ -97,11 +127,11 @@ $count = 0; // We've read at least some threads, are they here?- $query = $db->simple_select("threads", "lastpost, tid, fid", "visible=1 AND closed NOT LIKE 'moved|%' AND fid IN ({$fid}) AND lastpost > '{$cutoff}'{$onlyview}", array("limit" => 100));+ $query = $db->simple_select("threads", "lastpost, tid, fid", "visible=1 AND closed NOT LIKE 'moved|%' AND {$where} AND lastpost > '{$cutoff}'", array("limit" => 100)); while($thread = $db->fetch_array($query)) {- if(isset($threadsread[$thread['tid']]) && $thread['lastpost'] > (int)$threadsread[$thread['tid']] && isset($forumsread[$thread['fid']]) && $thread['lastpost'] > (int)$forumsread[$thread['fid']])+ if((!isset($threadsread[$thread['tid']]) || $thread['lastpost'] > (int)$threadsread[$thread['tid']]) && (!isset($forumsread[$thread['fid']]) || $thread['lastpost'] > (int)$forumsread[$thread['fid']])) { ++$count; }@@ -123,7 +153,7 @@ FROM ".TABLE_PREFIX."threads t LEFT JOIN ".TABLE_PREFIX."threadsread tr ON (tr.tid=t.tid AND tr.uid='{$mybb->user['uid']}') LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid=t.fid AND fr.uid='{$mybb->user['uid']}')- WHERE t.visible=1 AND t.closed NOT LIKE 'moved|%' AND t.fid IN ($fid) AND t.lastpost > COALESCE(tr.dateline,$cutoff) AND t.lastpost > COALESCE(fr.dateline,$cutoff) AND t.lastpost>$cutoff{$onlyview2}+ WHERE t.visible=1 AND t.closed NOT LIKE 'moved|%' AND {$where2} AND t.lastpost > COALESCE(tr.dateline,$cutoff) AND t.lastpost > COALESCE(fr.dateline,$cutoff) AND t.lastpost>$cutoff "); break; default:@@ -132,7 +162,7 @@ FROM ".TABLE_PREFIX."threads t LEFT JOIN ".TABLE_PREFIX."threadsread tr ON (tr.tid=t.tid AND tr.uid='{$mybb->user['uid']}') LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid=t.fid AND fr.uid='{$mybb->user['uid']}')- WHERE t.visible=1 AND t.closed NOT LIKE 'moved|%' AND t.fid IN ($fid) AND t.lastpost > IFNULL(tr.dateline,$cutoff) AND t.lastpost > IFNULL(fr.dateline,$cutoff) AND t.lastpost>$cutoff{$onlyview2}+ WHERE t.visible=1 AND t.closed NOT LIKE 'moved|%' AND {$where2} AND t.lastpost > IFNULL(tr.dateline,$cutoff) AND t.lastpost > IFNULL(fr.dateline,$cutoff) AND t.lastpost>$cutoff "); } return $db->fetch_field($query, "unread_count");
Vulnerability Existed: yes
SQL Injection - CWE-89 - inc/functions_indicators.php Lines 77-90
[Old Code]
```php
$permissions = forum_permissions($fid);
```
[Fixed Code]
```php
$forums = explode(',', $fid);
foreach($forums as $forum)
{
$permissions = forum_permissions($forum);
if(!empty($permissions['canonlyviewownthreads']))
{
$forums_own[] = $forum;
}
else
{
$forums_all[] = $forum;
}
}
if(!empty($forums_own))
{
$where = "(fid IN (".implode(',', $forums_own).") AND uid = {$mybb->user['uid']})";
$where2 = "(t.fid IN (".implode(',', $forums_own).") AND t.uid = {$mybb->user['uid']})";
}
if(!empty($forums_all))
{
if(isset($where))
{
$where = "({$where} OR fid IN (".implode(',', $forums_all)."))";
$where2 = "({$where2} OR t.fid IN (".implode(',', $forums_all)."))";
}
else
{
$where = 'fid IN ('.implode(',', $forums_all).')';
$where2 = 't.fid IN ('.implode(',', $forums_all).')';
}
}
```
Explanation:
The original code directly interpolated `$fid` into SQL queries (lines 130, 156, 165). While the fix still uses string concatenation via `implode()` without prepared statements, it introduces permission-based filtering by splitting the forum IDs and checking permissions per forum. This separates forums into those where users can only view their own threads (`$forums_own`) versus all threads (`$forums_all`), then builds conditional WHERE clauses (`$where`, `$where2`) that enforce these permissions in the SQL query itself. This mitigates privilege escalation by ensuring users cannot bypass forum-level access controls, even if they provide unauthorized forum IDs. However, the vulnerability is not fully eliminated since the code still uses string concatenation rather than parameterized queries or explicit input validation/escaping.
---
Vulnerability Existed: yes
TRUE POSITIVE
Logic Error / Incorrect Access Control - CWE-276 - inc/functions_indicators.php Line 134
[Old Code]
```php
if(isset($threadsread[$thread['tid']]) && $thread['lastpost'] > (int)$threadsread[$thread['tid']] && isset($forumsread[$thread['fid']]) && $thread['lastpost'] > (int)$forumsread[$thread['fid']])
```
[Fixed Code]
```php
if((!isset($threadsread[$thread['tid']]) || $thread['lastpost'] > (int)$threadsread[$thread['tid']]) && (!isset($forumsread[$thread['fid']]) || $thread['lastpost'] > (int)$forumsread[$thread['fid']]))
```
Explanation:
The original logic used AND operators requiring ALL conditions to be true: thread read entry must exist AND be older than current post AND forum read entry must exist AND be older than current post. This incorrect logic would fail to mark threads as unread if either the thread or forum read entry was missing, causing unread thread indicators to disappear incorrectly. The fix uses OR operators: treat as unread if thread read entry doesn't exist OR is older than the post, AND forum read entry doesn't exist OR is older than the post. This correctly identifies threads that have new posts since the user's last read timestamp.
--- cache/mybb_mybb_1807/inc/functions_modcp.php 2025-12-06 11:32:55.214127789 +0000+++ cache/mybb_mybb_1808/inc/functions_modcp.php 2025-12-06 11:32:55.974176867 +0000@@ -41,7 +41,7 @@ */ function fetch_forum_announcements($pid=0, $depth=1) {- global $mybb, $db, $lang, $theme, $announcements, $templates, $announcements_forum, $moderated_forums, $unviewableforums;+ global $mybb, $db, $lang, $theme, $announcements, $templates, $announcements_forum, $moderated_forums, $unviewableforums, $parser; static $forums_by_parent, $forum_cache, $parent_forums; if(!is_array($forum_cache))@@ -118,7 +118,7 @@ eval("\$icon = \"".$templates->get("modcp_announcements_announcement_active")."\";"); } - $subject = htmlspecialchars_uni($announcement['subject']);+ $subject = htmlspecialchars_uni($parser->parse_badwords($announcement['subject'])); eval("\$announcements_forum .= \"".$templates->get("modcp_announcements_announcement")."\";"); }@@ -145,43 +145,43 @@ { global $db, $lang, $forum, $mybb, $post, $thread, $reputation, $user; - $nummods = false;+ $modsjoin = $modswhere = ''; if(!empty($forum['parentlist'])) {- $query = $db->query("- SELECT DISTINCT u.username, u.email, u.receivepms, u.uid- FROM ".TABLE_PREFIX."moderators m- LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=m.id)- WHERE m.fid IN (".$forum['parentlist'].") AND m.isgroup = '0'- ");-- $nummods = $db->num_rows($query);- }-- if(!$nummods)- {- unset($query);- switch($db->type)- {- case "pgsql":- case "sqlite":- $query = $db->query("- SELECT u.username, u.email, u.receivepms, u.uid- FROM ".TABLE_PREFIX."users u- LEFT JOIN ".TABLE_PREFIX."usergroups g ON (((','|| u.additionalgroups|| ',' LIKE '%,'|| g.gid|| ',%') OR u.usergroup = g.gid))- WHERE (g.cancp=1 OR g.issupermod=1)- ");- break;- default:- $query = $db->query("- SELECT u.username, u.email, u.receivepms, u.uid- FROM ".TABLE_PREFIX."users u- LEFT JOIN ".TABLE_PREFIX."usergroups g ON (((CONCAT(',', u.additionalgroups, ',') LIKE CONCAT('%,', g.gid, ',%')) OR u.usergroup = g.gid))- WHERE (g.cancp=1 OR g.issupermod=1)- ");+ $modswhere = "m.fid IN ({$forum['parentlist']}) OR ";++ if($db->type == 'pgsql' || $db->type == 'sqlite')+ {+ $modsjoin = "LEFT JOIN {$db->table_prefix}moderators m ON (m.id = u.uid AND m.isgroup = 0) OR ((m.id = u.usergroup OR ',' || u.additionalgroups || ',' LIKE '%,' || m.id || ',%') AND m.isgroup = 1)";+ }+ else+ {+ $modsjoin = "LEFT JOIN {$db->table_prefix}moderators m ON (m.id = u.uid AND m.isgroup = 0) OR ((m.id = u.usergroup OR CONCAT(',', u.additionalgroups, ',') LIKE CONCAT('%,', m.id, ',%')) AND m.isgroup = 1)"; } } + switch($db->type)+ {+ case "pgsql":+ case "sqlite":+ $query = $db->query("+ SELECT DISTINCT u.username, u.email, u.receivepms, u.uid+ FROM {$db->table_prefix}users u+ {$modsjoin}+ LEFT JOIN {$db->table_prefix}usergroups g ON (',' || u.additionalgroups || ',' LIKE '%,' || g.gid || ',%' OR g.gid = u.usergroup)+ WHERE {$modswhere}g.cancp = 1 OR g.issupermod = 1+ ");+ break;+ default:+ $query = $db->query("+ SELECT DISTINCT u.username, u.email, u.receivepms, u.uid+ FROM {$db->table_prefix}users u+ {$modsjoin}+ LEFT JOIN {$db->table_prefix}usergroups g ON (CONCAT(',', u.additionalgroups, ',') LIKE CONCAT('%,', g.gid, ',%') OR g.gid = u.usergroup)+ WHERE {$modswhere}g.cancp = 1 OR g.issupermod = 1+ ");+ }+ $lang_string_subject = "emailsubject_report{$report_type}"; $lang_string_message = "email_report{$report_type}"; @@ -273,6 +273,7 @@ 'id3' => (int)$report['id3'], 'uid' => (int)$report['uid'], 'reportstatus' => 0,+ 'reasonid' => (int)$report['reasonid'], 'reason' => $db->escape_string($report['reason']), 'type' => $db->escape_string($type), 'reports' => 1,@@ -283,7 +284,7 @@ if($mybb->settings['reportmethod'] == "email" || $mybb->settings['reportmethod'] == "pms") {- return send_report($report, $type);+ send_report($report, $type); } $rid = $db->insert_query("reportedcontent", $insert_array);
```
Vulnerability Existed: no
SQL Injection - CWE-89 - inc/functions_modcp.php [148-183]
[Old Code]
$query = $db->query("
SELECT DISTINCT u.username, u.email, u.receivepms, u.uid
FROM ".TABLE_PREFIX."moderators m
LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=m.id)
WHERE m.fid IN (".$forum['parentlist'].") AND m.isgroup = '0'
");
[Fixed Code]
$modswhere = "m.fid IN ({$forum['parentlist']}) OR ";
...
$query = $db->query("
SELECT DISTINCT u.username, u.email, u.receivepms, u.uid
FROM {$db->table_prefix}users u
{$modsjoin}
...
WHERE {$modswhere}g.cancp = 1 OR g.issupermod = 1
");
Explanation:
The original code and fixed code both use unsanitized variable interpolation in SQL strings. The `$forum['parentlist']` variable is directly interpolated into the SQL query without parameterized queries or prepared statements in both versions. However, this is a refactoring that consolidates multiple query branches into a single parameterized structure. The vulnerability pattern remains similar, but the code organization suggests the application relies on upstream validation of `$forum['parentlist']` (likely validated when the forum list is constructed). No new SQL injection vulnerability was introduced by this change; the refactoring maintains the same trust model as the original code.
```
```
Vulnerability Existed: no
Cross-Site Scripting (XSS) - CWE-79 - inc/functions_modcp.php [121]
[Old Code]
$subject = htmlspecialchars_uni($announcement['subject']);
[Fixed Code]
$subject = htmlspecialchars_uni($parser->parse_badwords($announcement['subject']));
Explanation:
The fix actually improves security by adding word filtering via `parse_badwords()` before HTML encoding. The original code applies only HTML encoding (`htmlspecialchars_uni`), which prevents XSS in most contexts. The fix adds an additional layer of content filtering via the parser. This is a security enhancement, not a fix for an existing vulnerability. No XSS vulnerability was introduced or fixed by this specific change.
```
```
Vulnerability Existed: no
Return Value Handling - CWE-252 - inc/functions_modcp.php [286]
[Old Code]
return send_report($report, $type);
[Fixed Code]
send_report($report, $type);
Explanation:
The change removes the return statement from the `send_report()` function call. Without seeing the broader function context, this appears to be intentional logic change rather than a security vulnerability fix. If the return value of `send_report()` was previously used to convey success/failure status, removing it could mask errors. However, this is a control flow change, not a security fix. The code should verify whether the calling function still properly handles errors from `send_report()`.
```
--- cache/mybb_mybb_1807/inc/functions_online.php 2025-12-06 11:32:55.214127789 +0000+++ cache/mybb_mybb_1808/inc/functions_online.php 2025-12-06 11:32:55.974176867 +0000@@ -600,12 +600,12 @@ $query = $db->simple_select("users", "uid,username", "uid IN ($uid_sql)"); while($user = $db->fetch_array($query)) {- $usernames[$user['uid']] = $user['username'];+ $usernames[$user['uid']] = htmlspecialchars_uni($user['username']); } } else {- $usernames[$mybb->user['uid']] = $mybb->user['username'];+ $usernames[$mybb->user['uid']] = htmlspecialchars_uni($mybb->user['username']); } } @@ -1141,7 +1141,7 @@ $invisible_mark = ''; } - $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']);+ $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); $online_name = build_profile_link($user['username'], $user['uid']).$invisible_mark; } }
Vulnerability Existed: yes TRUE POSITIVE Cross-Site Scripting (XSS) - CWE-79 - inc/functions_online.php Lines 603, 609, 1144 Old Code: ```php $usernames[$user['uid']] = $user['username']; $usernames[$mybb->user['uid']] = $mybb->user['username']; $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']); ``` Fixed Code: ```php $usernames[$user['uid']] = htmlspecialchars_uni($user['username']); $usernames[$mybb->user['uid']] = htmlspecialchars_uni($mybb->user['username']); $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); ``` Explanation: User-supplied usernames retrieved from the database were being directly stored and used without HTML entity encoding before being output in templates. This is a reflected XSS vulnerability where a malicious username could contain JavaScript code that executes in other users' browsers when viewing online user lists. The fix applies `htmlspecialchars_uni()` (MyBB's HTML encoding function) to escape special characters before storage/usage, preventing the injection of malicious HTML/JavaScript. This is a critical fix for a stored/reflected XSS vulnerability in user-facing online status displays.
--- cache/mybb_mybb_1807/inc/functions_post.php 2025-12-06 11:32:55.218128048 +0000+++ cache/mybb_mybb_1808/inc/functions_post.php 2025-12-06 11:32:55.974176867 +0000@@ -127,6 +127,9 @@ break; } + $post['username'] = htmlspecialchars_uni($post['username']);+ $post['userusername'] = htmlspecialchars_uni($post['userusername']);+ if(!$postcounter) { // Used to show the # of the post if($page > 1)@@ -539,6 +542,7 @@ { $post['editdate'] = my_date('relative', $post['edittime']); $post['editnote'] = $lang->sprintf($lang->postbit_edited, $post['editdate']);+ $post['editusername'] = htmlspecialchars_uni($post['editusername']); $post['editedprofilelink'] = build_profile_link($post['editusername'], $post['edituid']); $editreason = ""; if($post['editreason'] != "")@@ -745,7 +749,7 @@ "allow_mycode" => $mybb->settings['sigmycode'], "allow_smilies" => $mybb->settings['sigsmilies'], "allow_imgcode" => $mybb->settings['sigimgcode'],- "me_username" => $post['username'],+ "me_username" => $parser_options['me_username'], "filter_badwords" => 1 );
Analyzing the provided code diff for security vulnerabilities... --- **Vulnerability 1:** Vulnerability Existed: yes TRUE POSITIVE Cross-Site Scripting (XSS) - CWE-79 - inc/functions_post.php Lines 130-131 **Old Code:** ```php // No escaping applied to $post['username'] and $post['userusername'] ``` **Fixed Code:** ```php $post['username'] = htmlspecialchars_uni($post['username']); $post['userusername'] = htmlspecialchars_uni($post['userusername']); ``` Explanation: The `$post['username']` and `$post['userusername']` variables were being used in output contexts without HTML escaping. If these values contained user-controlled data (which they do, being from post records), an attacker could inject malicious JavaScript code that would execute in other users' browsers. The fix applies `htmlspecialchars_uni()` to escape HTML special characters, preventing XSS attacks. --- **Vulnerability 2:** Vulnerability Existed: yes TRUE POSITIVE Cross-Site Scripting (XSS) - CWE-79 - inc/functions_post.php Line 545 **Old Code:** ```php $post['editedprofilelink'] = build_profile_link($post['editusername'], $post['edituid']); ``` **Fixed Code:** ```php $post['editusername'] = htmlspecialchars_uni($post['editusername']); $post['editedprofilelink'] = build_profile_link($post['editusername'], $post['edituid']); ``` Explanation: Similar to Vulnerability 1, the `$post['editusername']` variable was not being escaped before being passed to `build_profile_link()`. If this function uses the username in HTML output without additional escaping, it could result in an XSS vulnerability. The fix ensures the username is HTML-escaped before use. --- **Vulnerability 3:** Vulnerability Existed: yes TRUE POSITIVE Cross-Site Scripting (XSS) - CWE-79 - inc/functions_post.php Line 752 **Old Code:** ```php "me_username" => $post['username'], ``` **Fixed Code:** ```php "me_username" => $parser_options['me_username'], ``` Explanation: This change fixes a logic error that likely masked an XSS vulnerability. Using `$post['username']` directly (unescaped) in parser options could allow injection. The fix uses `$parser_options['me_username']` which should be a properly sanitized value. This prevents untrusted username data from being passed to the parser where it could be used in output without proper escaping.
--- cache/mybb_mybb_1807/inc/functions_serverstats.php 2025-12-06 11:32:55.222128307 +0000+++ cache/mybb_mybb_1808/inc/functions_serverstats.php 2025-12-06 11:32:55.982177385 +0000@@ -212,7 +212,7 @@ // Check the hosting company if(strpos($_SERVER['HTTP_HOST'], ".") !== false) {- $host_url = "http://www.whoishostingthis.com/".str_replace(array('http://', 'www.'), '', $_SERVER['HTTP_HOST']);+ $host_url = "http://www.whoishostingthis.com/".str_replace(array('http://', 'https://', 'www.'), '', $_SERVER['HTTP_HOST']); $hosting = fetch_remote_file($host_url); @@ -278,7 +278,7 @@ $amp = "&"; } - $server_stats_url = 'http://community.mybb.com/server_stats.php?'.$string;+ $server_stats_url = 'https://community.mybb.com/server_stats.php?'.$string; $return = array(); $return['info_sent_success'] = false;
Vulnerability Existed: no
[No Vulnerability] - [N/A] - inc/functions_serverstats.php [Lines 215, 281]
Old Code (Line 215):
```php
$host_url = "http://www.whoishostingthis.com/".str_replace(array('http://', 'www.'), '', $_SERVER['HTTP_HOST']);
```
Fixed Code (Line 215):
```php
$host_url = "http://www.whoishostingthis.com/".str_replace(array('http://', 'https://', 'www.'), '', $_SERVER['HTTP_HOST']);
```
Explanation:
This change adds 'https://' to the array of strings to be removed from `$_SERVER['HTTP_HOST']`. This is a security improvement that ensures both HTTP and HTTPS protocols are properly stripped from the host value before constructing the lookup URL. While the original code was not technically "vulnerable" in the sense of introducing a new security flaw, it was incomplete in handling HTTPS-based hostnames. Adding 'https://' ensures consistent and correct behavior regardless of the protocol used to access the server. This is defensive coding rather than fixing an active vulnerability.
---
Vulnerability Existed: no
[No Vulnerability] - [N/A] - inc/functions_serverstats.php [Lines 281]
Old Code (Line 281):
```php
$server_stats_url = 'http://community.mybb.com/server_stats.php?'.$string;
```
Fixed Code (Line 281):
```php
$server_stats_url = 'https://community.mybb.com/server_stats.php?'.$string;
```
Explanation:
This change upgrades the URL scheme from HTTP to HTTPS when communicating with the MyBB community statistics server. This is a security best practice that prevents potential man-in-the-middle (MITM) attacks by ensuring the connection to the remote server is encrypted. While not a "fix" for a vulnerability in the traditional sense, it improves the security posture by ensuring data sent to the remote statistics service is transmitted over a secure, encrypted channel. This prevents interception of any potentially sensitive information included in the query string.
--- cache/mybb_mybb_1807/inc/functions_upload.php 2025-12-06 11:32:55.226128564 +0000+++ cache/mybb_mybb_1808/inc/functions_upload.php 2025-12-06 11:32:55.982177385 +0000@@ -288,16 +288,21 @@ } } - // Next check the file size- if($avatar['size'] > ($mybb->settings['avatarsize']*1024) && $mybb->settings['avatarsize'] > 0)+ // Check a list of known MIME types to establish what kind of avatar we're uploading+ $attachtypes = (array)$cache->read('attachtypes');++ $allowed_mime_types = array();+ foreach($attachtypes as $attachtype) {- delete_uploaded_file($avatarpath."/".$filename);- $ret['error'] = $lang->error_uploadsize;- return $ret;+ if(defined('IN_ADMINCP') || is_member($attachtype['groups']) && $attachtype['avatarfile'])+ {+ $allowed_mime_types[$attachtype['mimetype']] = $attachtype['maxsize'];+ } } - // Check a list of known MIME types to establish what kind of avatar we're uploading- switch(my_strtolower($avatar['type']))+ $avatar['type'] = my_strtolower($avatar['type']);++ switch($avatar['type']) { case "image/gif": $img_type = 1;@@ -313,17 +318,31 @@ case "image/x-png": $img_type = 3; break;+ case "image/bmp":+ case "image/x-bmp":+ case "image/x-windows-bmp":+ $img_type = 6;+ break; default: $img_type = 0; } // Check if the uploaded file type matches the correct image type (returned by getimagesize)- if($img_dimensions[2] != $img_type || $img_type == 0)+ if(empty($allowed_mime_types[$avatar['type']]) || $img_dimensions[2] != $img_type || $img_type == 0) { $ret['error'] = $lang->error_uploadfailed; delete_uploaded_file($avatarpath."/".$filename); return $ret; }++ // Next check the file size+ if(($avatar['size'] > ($mybb->settings['avatarsize']*1024) && $mybb->settings['avatarsize'] > 0) || $avatar['size'] > $allowed_mime_types[$avatar['type']] && !($mybb->settings['avatarsize'] > 0))+ {+ delete_uploaded_file($avatarpath."/".$filename);+ $ret['error'] = $lang->error_uploadsize;+ return $ret;+ }+ // Everything is okay so lets delete old avatars for this user remove_avatars($uid, $filename); @@ -386,9 +405,18 @@ return $ret; } - $attachtypes = $cache->read('attachtypes');+ $attachtypes = (array)$cache->read('attachtypes'); $attachment = $plugins->run_hooks("upload_attachment_start", $attachment); + $allowed_mime_types = array();+ foreach($attachtypes as $ext => $attachtype)+ {+ if(!is_member($attachtype['groups']) || ($attachtype['forums'] != -1 && strpos(','.$attachtype['forums'].',', ','.$forum['fid'].',') === false))+ {+ unset($attachtypes[$ext]);+ }+ }+ $ext = get_extension($attachment['name']); // Check if we have a valid extension if(!isset($attachtypes[$ext]))
Based on my analysis of the diff for the `upload_avatar()` function in `inc/functions_upload.php`, here are the security vulnerabilities identified:
---
## Vulnerability 1: Unrestricted File Size (MIME Type Based)
**Vulnerability Existed:** yes
**CWE-434 - Unrestricted Upload of File with Dangerous Type - inc/functions_upload.php Lines 338-344**
**Old Code:**
```php
// Next check the file size
if($avatar['size'] > ($mybb->settings['avatarsize']*1024) && $mybb->settings['avatarsize'] > 0)
{
delete_uploaded_file($avatarpath."/".$filename);
$ret['error'] = $lang->error_uploadsize;
return $ret;
}
```
**Fixed Code:**
```php
// Next check the file size
if(($avatar['size'] > ($mybb->settings['avatarsize']*1024) && $mybb->settings['avatarsize'] > 0) || $avatar['size'] > $allowed_mime_types[$avatar['type']] && !($mybb->settings['avatarsize'] > 0))
{
delete_uploaded_file($avatarpath."/".$filename);
$ret['error'] = $lang->error_uploadsize;
return $ret;
}
```
**Explanation:**
The vulnerability was that the original code only checked against a global `avatarsize` setting without validating the MIME type-specific size limits from the `attachtypes` cache. An attacker could upload a very large image file that exceeds MIME-type-specific limits if the global `avatarsize` was not set (or was 0). The fix adds an additional check: `$avatar['size'] > $allowed_mime_types[$avatar['type']]` which enforces per-MIME-type size limits, preventing oversized uploads of specific image types.
---
## Vulnerability 2: Missing MIME Type Whitelist Validation
**Vulnerability Existed:** yes
**CWE-434 - Unrestricted Upload of File with Dangerous Type - inc/functions_upload.php Line 331**
**Old Code:**
```php
if($img_dimensions[2] != $img_type || $img_type == 0)
{
$ret['error'] = $lang->error_uploadfailed;
delete_uploaded_file($avatarpath."/".$filename);
return $ret;
}
```
**Fixed Code:**
```php
if(empty($allowed_mime_types[$avatar['type']]) || $img_dimensions[2] != $img_type || $img_type == 0)
{
$ret['error'] = $lang->error_uploadfailed;
delete_uploaded_file($avatarpath."/".$filename);
return $ret;
}
```
**Explanation:**
The original code did not validate that the MIME type is in the `$allowed_mime_types` array before allowing upload. This meant that even if a user group didn't have permission to upload certain MIME types (checked via `is_member($attachtype['groups'])` and `$attachtype['avatarfile']`), the MIME type validation was incomplete. The fix adds `empty($allowed_mime_types[$avatar['type']])` check, ensuring that only MIME types that are both (1) in the cache and (2) allowed for the user's group are accepted.
---
## Vulnerability 3: Potential Logic Error in File Size Check (Order of Operations)
**Vulnerability Existed:** not sure
**CWE-469 - Use of Pointer Arithmetic with Unexpected Operators - inc/functions_upload.php Line 339**
**Old Code:**
```php
// N/A - this logic didn't exist
```
**Fixed Code:**
```php
if(($avatar['size'] > ($mybb->settings['avatarsize']*1024) && $mybb->settings['avatarsize'] > 0) || $avatar['size'] > $allowed_mime_types[$avatar['type']] && !($mybb->settings['avatarsize'] > 0))
```
**Explanation:**
The new file size check has potential operator precedence issues. The condition `$avatar['size'] > $allowed_mime_types[$avatar['type']] && !($mybb->settings['avatarsize'] > 0)` may not behave as intended due to `&&` binding tighter than `||`. The second part should likely be wrapped in parentheses: `($avatar['size'] > $allowed_mime_types[$avatar['type']] && !($mybb->settings['avatarsize'] > 0))`. However, it's also possible this is intentional—if `avatarsize` is 0 (unlimited), then check against MIME-type-specific limits. Without knowing the original intent, this is uncertain, but the logic appears correct for enforcing per-MIME-type limits as a fallback.
--- cache/mybb_mybb_1807/inc/functions_user.php 2025-12-06 11:32:55.226128564 +0000+++ cache/mybb_mybb_1808/inc/functions_user.php 2025-12-06 11:32:55.982177385 +0000@@ -127,6 +127,7 @@ * @param string $password The md5()'ed password. * @param string $salt (Optional) The salt of the user. * @return array The new password.+ * @deprecated deprecated since version 1.8.6 Please use other alternatives. */ function update_password($uid, $password, $salt="") {
Vulnerability Existed: no No CWE/Vulnerability Identified - N/A - inc/functions_user.php - Lines 130 [Old Code] ``` * @return array The new password. */ function update_password($uid, $password, $salt="") ``` [Fixed Code] ``` * @return array The new password. * @deprecated deprecated since version 1.8.6 Please use other alternatives. */ function update_password($uid, $password, $salt="") ``` Explanation: This diff adds a deprecation notice to the PHPDoc comment of the `update_password()` function. This is a documentation-only change that marks the function as deprecated in version 1.8.6, recommending users to use alternative methods. No code logic was modified, no security vulnerabilities were introduced or fixed, and the change does not alter the function's behavior. This is a best practice notification to developers that this function should no longer be used in new code.
--- cache/mybb_mybb_1807/inc/languages/english.php 2025-12-06 11:32:55.230128823 +0000+++ cache/mybb_mybb_1808/inc/languages/english.php 2025-12-06 11:32:55.982177385 +0000@@ -12,10 +12,10 @@ $langinfo['author'] = "MyBB Group"; // The language authors website-$langinfo['website'] = "http://www.mybb.com/";+$langinfo['website'] = "https://mybb.com/"; // Compatible version of MyBB-$langinfo['version'] = "1807";+$langinfo['version'] = "1808"; // Sets if the translation includes the Admin CP (1 = yes, 0 = no) $langinfo['admin'] = 1;
Vulnerability Existed: no No vulnerabilities detected in this diff. Explanation: This diff contains only non-security configuration updates: 1. **Website URL upgrade (HTTP to HTTPS)**: Changed `http://www.mybb.com/` to `https://mybb.com/`. This is a security improvement, not a fix for a vulnerability in the code itself—it's a metadata update to use a secure protocol. 2. **Version string update**: Changed language pack version from "1807" to "1808". This is a simple version bump with no security implications. Both changes are benign metadata updates that do not introduce, fix, or relate to code vulnerabilities. No CWE, injection, authentication, authorization, or data handling issues are present.
--- cache/mybb_mybb_1807/inc/languages/english/admin/config_attachment_types.lang.php 2025-12-06 11:32:55.230128823 +0000+++ cache/mybb_mybb_1808/inc/languages/english/admin/config_attachment_types.lang.php 2025-12-06 11:32:55.982177385 +0000@@ -42,3 +42,12 @@ $l['confirm_attachment_type_deletion'] = "Are you sure you wish to delete this attachment type?"; +$l['success_activated_attachment_type'] = 'The selected attachment type has been activated successfully.';+$l['success_deactivated_attachment_type'] = 'The selected attachment type has been deactivated successfully.';++$l['enabled'] = "Enabled?";+$l['avatar_file'] = 'Avatar File';+$l['avatar_file_desc'] = 'Do you want to allow this attachment type to be used for avatars?';++$l['available_to_groups'] = 'Available to groups';+$l['available_in_forums'] = 'Available in forums';\ No newline at end of file
Vulnerability Existed: no No vulnerabilities detected in this diff. Explanation: This diff adds new language string definitions to a PHP language file (`inc/languages/english/admin/config_attachment_types.lang.php`). The changes consist entirely of adding new localized string constants to the `$l` array with descriptive text for UI elements related to attachment type management (activation/deactivation status, avatar file settings, and group/forum availability). These are static string definitions with no dynamic input, variable interpolation, code execution, or security-sensitive operations. The strings are simple labels and messages used for user interface display. There are no injection vectors, unsafe functions, or insecure patterns introduced.
--- cache/mybb_mybb_1807/inc/languages/english/admin/config_banning.lang.php 2025-12-06 11:32:55.230128823 +0000+++ cache/mybb_mybb_1808/inc/languages/english/admin/config_banning.lang.php 2025-12-06 11:32:55.982177385 +0000@@ -16,7 +16,6 @@ $l['banned_ip_addresses'] = "Banned IP Addresses"; $l['username'] = "Username";-$l['search_user'] = "Search for a user"; $l['date_disallowed'] = "Date Disallowed"; $l['last_attempted_use'] = "Last Attempted Use"; $l['email_address'] = "Email Address";
Vulnerability Existed: no No Security Vulnerability Detected - Language File Change Explanation: This diff shows a simple removal of a language string definition from a PHP language file. The line being removed is: ```php $l['search_user'] = "Search for a user"; ``` This is a straightforward localization/language configuration change with no security implications. The modification: - Does not involve any code execution - Does not handle user input, authentication, or sensitive data - Does not introduce or remove security controls - Is simply removing an unused language constant from the admin configuration This type of change (removing unused language strings) is a common maintenance task and poses no security risk. There are no vulnerabilities introduced or fixed in this diff.
--- cache/mybb_mybb_1807/inc/languages/english/admin/config_module_meta.lang.php 2025-12-06 11:32:55.230128823 +0000+++ cache/mybb_mybb_1808/inc/languages/english/admin/config_module_meta.lang.php 2025-12-06 11:32:55.982177385 +0000@@ -24,6 +24,7 @@ $l['warning_system'] = "Warning System"; $l['thread_prefixes'] = "Thread Prefixes"; $l['security_questions'] = "Security Questions";+$l['report_reasons'] = "Report Reasons"; $l['can_manage_settings'] = "Can manage settings?"; $l['can_manage_banned_accounts'] = "Can manage banned accounts?";@@ -42,4 +43,5 @@ $l['can_manage_mod_tools'] = "Can manage moderator tools?"; $l['can_manage_thread_prefixes'] = "Can manage thread prefixes?"; $l['can_manage_security_questions'] = "Can manage security questions?";+$l['can_manage_report_reasons'] = "Can manage report reasons?";
Vulnerability Existed: no This is a language file update that adds two new localization strings for a "Report Reasons" feature in MyBB's admin panel. The changes are purely additive (two new string definitions) and contain no executable code that could introduce security vulnerabilities. The additions: - `$l['report_reasons'] = "Report Reasons";` - `$l['can_manage_report_reasons'] = "Can manage report reasons?";` These are simple string assignments used for UI labels and messages. There is no: - User input processing - Code execution - Data manipulation - Authentication/authorization logic - SQL queries - External API calls - File operations - Or any other potentially dangerous operations Explanation: Language files in MyBB are configuration files that contain only static string definitions. They are not executable code and do not process any data or user input. This is a standard localization addition with no security implications.
--- /dev/null+++ cache/mybb_mybb_1808/inc/languages/english/admin/config_report_reasons.lang.php@@ -0,0 +1,65 @@+<?php+/**+ * MyBB 1.8 English Language Pack+ * Copyright 2014 MyBB Group, All Rights Reserved+ *+ */++$l['report_reasons'] = "Report Reasons";+$l['report_reasons_desc'] = "Here you can create and manage reasons that can be selecting when users report content.";+$l['add_new_reason'] = "Add New Reason";+$l['add_new_reason_desc'] = "Add a new reason for users to select when reporting content.";+$l['edit_reason'] = "Edit Reason";+$l['edit_reason_desc'] = "Edit a reason for users to select when reporting content.";++$l['applies_to'] = "Applies To";+$l['order'] = "Order";+$l['extra_comment'] = "Require Comment?";+$l['options'] = "Options";+$l['delete_reason'] = "Delete Reason";+$l['no_report_reasons'] = "There are no report reasons on your forum at this time.";++$l['reason_title'] = "Title";+$l['reason_title_desc'] = "Enter the title of the reason for reporting the content.";+$l['requires_extra'] = "Require An Extra Comment?";+$l['requires_extra_desc'] = "Require the user to enter an additional comment when this reason is selected?";+$l['save_reason'] = "Save Reason";++$l['content_colon'] = "Content:";++$l['all_content'] = "All content";+$l['select_content'] = "Select content";++// Content types+$l['report_content_'] = "None";+$l['report_content_all'] = "All";+$l['report_content_post'] = "Post";+$l['report_content_profile'] = "Profile";+$l['report_content_reputation'] = "Reputation";++// Content reasons+$l['report_reason_rules'] = "Breaks Forum Rules";+$l['report_reason_bad'] = "Inappropriate Content";+$l['report_reason_spam'] = "Spam Content";+$l['report_reason_wrong'] = "Wrong Forum";+$l['report_reason_other'] = "Other";++$l['default_report_reason'] = "Default";+$l['custom_report_reason'] = "Custom";++$l['update_reasons_order'] = "Update Reasons Order";++$l['error_cannot_modify_reason'] = "You cannot modify this reason.";+$l['error_cannot_delete_reason'] = "You cannot delete this reason.";+$l['error_invalid_reason'] = "You have selected an invalid reason.";+$l['error_missing_title'] = "You did not enter a title for this reason.";+//$l['error_missing_applies_to'] = "You did not select what content this reason applies to.";+$l['error_missing_extra'] = "You did not select if you want extra information for this reason.";++$l['success_reasons_disporder_updated'] = "The report reason display orders have been updated successfully.";+$l['success_reason_created'] = "The reason has been created successfully.";+$l['success_reason_updated'] = "The reason has been updated successfully.";+$l['success_reason_deleted'] = "The reason has been deleted successfully.";++$l['confirm_reason_deletion'] = "Are you sure you wish to delete this reason?";+
Vulnerability Existed: no This is a new language file (configuration/localization file) containing only static string definitions. There are no security vulnerabilities present. Explanation: The file consists entirely of PHP variable assignments for language strings used in the MyBB forum software's admin panel. These are: - Static language constants with no user input processing - No database queries or operations - No file operations or system calls - No variable interpolation or dynamic code execution - No authentication/authorization logic - No cryptographic operations Language/localization files like this are inherently safe as they contain only predefined text content with no executable logic or security-sensitive operations. The file follows standard MyBB localization conventions and poses no security risk.
--- cache/mybb_mybb_1807/inc/languages/english/admin/config_settings.lang.php 2025-12-06 11:32:55.230128823 +0000+++ cache/mybb_mybb_1808/inc/languages/english/admin/config_settings.lang.php 2025-12-06 11:32:55.982177385 +0000@@ -83,13 +83,16 @@ $l['error_cannot_edit_php'] = "This is a special type of setting which cannot be edited."; $l['error_ajax_search'] = "There was a problem searching for settings:"; $l['error_ajax_unknown'] = "An unknown error occurred while searching for settings.";-$l['error_chmod_settings_file'] = "The settings file \"./inc/settings.php\" isn't writable. Please CHMOD to 777.<br />For more information on CHMODing, see the <a href=\"http://docs.mybb.com/HowTo_Chmod.html\" target=\"_blank\">MyBB Docs</a>.";-$l['error_hidden_captcha_conflict'] = "The hidden captcha value cannot be \"{1}\" as it conflicts with another registration field.";+$l['error_chmod_settings_file'] = "The settings file \"./inc/settings.php\" isn't writable. Please CHMOD to 777.<br />For more information on CHMODing, see the <a href=\"https://docs.mybb.com/1.8/administration/security/file-permissions\" target=\"_blank\">MyBB Docs</a>."; $l['success_setting_added'] = "The setting has been created successfully."; $l['success_setting_updated'] = "The setting has been updated successfully."; $l['success_setting_deleted'] = "The selected setting has been deleted successfully."; $l['success_settings_updated'] = "The settings have been updated successfully.";+$l['success_settings_updated_hiddencaptchaimage'] = '<div class="smalltext" style="font-weight: normal;">Please note that the <strong>Hidden CAPTCHA field</strong> setting was reverted to <strong>{1}</strong> due to a conflict with the <strong>{2}</strong> field in the registration form.</div>';+$l['success_settings_updated_username_method'] = '<div class="smalltext" style="font-weight: normal;">Please note that the <b>Allowed Login Methods</b> setting was not updated due to multiple users using the same e-mail address at this time.</div>';+$l['success_settings_updated_allowmultipleemails'] = '<div class="smalltext" style="font-weight: normal;">Please note that the <b>Allow emails to be registered multiple times?</b> setting can\'t be enabled because the <b>Allowed Login Methods</b> setting allows users to login by e-mail address.</div>';+$l['success_settings_updated_captchaimage'] = '<div class="smalltext" style="font-weight: normal;">Please note that the <strong>CAPTCHA Images for Registration & Posting</strong> setting was reverted to <strong>MyBB Default Captcha</strong> due to the lack of public/private key(s).</div>'; $l['success_display_orders_updated'] = "The setting display orders have been updated successfully."; $l['success_setting_group_added'] = "The setting group has been created successfully."; $l['success_setting_group_updated'] = "The setting group has been updated successfully.";
```
Vulnerability Existed: no
HTTP to HTTPS Upgrade - No CWE (Information Security Best Practice) - inc/languages/english/admin/config_settings.lang.php - Line 86
Old Code:
$l['error_chmod_settings_file'] = "The settings file \"./inc/settings.php\" isn't writable. Please CHMOD to 777.<br />For more information on CHMODing, see the <a href=\"http://docs.mybb.com/HowTo_Chmod.html\" target=\"_blank\">MyBB Docs</a>.";
Fixed Code:
$l['error_chmod_settings_file'] = "The settings file \"./inc/settings.php\" isn't writable. Please CHMOD to 777.<br />For more information on CHMODing, see the <a href=\"https://docs.mybb.com/1.8/administration/security/file-permissions\" target=\"_blank\">MyBB Docs</a>.";
Explanation:
This is not a vulnerability fix but a security best practice improvement. The change upgrades an HTTP link to HTTPS and updates the documentation URL path. This prevents man-in-the-middle attacks on the documentation link and ensures the user is directed to the correct, current documentation page. No actual vulnerability existed in the old code—this is a proactive security hardening measure.
```
```
Vulnerability Existed: no
No Security Vulnerability - Addition of User-Facing Messages - inc/languages/english/admin/config_settings.lang.php - Lines 91-94
Old Code:
(Lines did not exist)
Fixed Code:
$l['success_settings_updated_hiddencaptchaimage'] = '<div class="smalltext" style="font-weight: normal;">Please note that the <strong>Hidden CAPTCHA field</strong> setting was reverted to <strong>{1}</strong> due to a conflict with the <strong>{2}</strong> field in the registration form.</div>';
$l['success_settings_updated_username_method'] = '<div class="smalltext" style="font-weight: normal;">Please note that the <b>Allowed Login Methods</b> setting was not updated due to multiple users using the same e-mail address at this time.</div>';
$l['success_settings_updated_allowmultipleemails'] = '<div class="smalltext" style="font-weight: normal;">Please note that the <b>Allow emails to be registered multiple times?</b> setting can\'t be enabled because the <b>Allowed Login Methods</b> setting allows users to login by e-mail address.</div>';
$l['success_settings_updated_captchaimage'] = '<div class="smalltext" style="font-weight: normal;">Please note that the <strong>CAPTCHA Images for Registration & Posting</strong> setting was reverted to <strong>MyBB Default Captcha</strong> due to the lack of public/private key(s).</div>';
Explanation:
These are new language strings added for informational/warning messages to administrators. They contain properly HTML-escaped content (using `&` for ampersands and escaped single quotes). No security vulnerabilities are introduced—these are user-facing messages with no injection vectors or sensitive data exposure.
```
**Summary:** This diff represents a security hardening improvement (HTTPS upgrade) and adds new administrative notification messages. No actual vulnerabilities were fixed or introduced.
--- cache/mybb_mybb_1807/inc/languages/english/admin/global.lang.php 2025-12-06 11:32:55.234129081 +0000+++ cache/mybb_mybb_1808/inc/languages/english/admin/global.lang.php 2025-12-06 11:32:55.986177642 +0000@@ -133,6 +133,8 @@ $l['off'] = "Off"; $l['alt_enabled'] = "Enabled"; $l['alt_disabled'] = "Disabled";+$l['enable'] = "Enable";+$l['disable'] = "Disable"; $l['saved'] = 'Saved'; $l['rel_in'] = "In ";@@ -176,7 +178,7 @@ $l['loading_text'] = "Loading<br />Please wait..."; // Time zone selection boxes-$l['timezone_gmt_minus_1200'] = "(GMT -12:00) Marshall Islands";+$l['timezone_gmt_minus_1200'] = "(GMT -12:00) Howland and Baker Islands"; $l['timezone_gmt_minus_1100'] = "(GMT -11:00) Nome, Midway Island"; $l['timezone_gmt_minus_1000'] = "(GMT -10:00) Hawaii, Papeete"; $l['timezone_gmt_minus_950'] = "(GMT -9:30) Marquesas Islands";@@ -205,13 +207,15 @@ $l['timezone_gmt_650'] = "(GMT +6:30) Yangon"; $l['timezone_gmt_700'] = "(GMT +7:00) Bangkok, Hanoi, Jakarta"; $l['timezone_gmt_800'] = "(GMT +8:00) Beijing, Hong Kong, Perth, Singapore, Taipei, Manila";+$l['timezone_gmt_850'] = "(GMT +8:30) Pyongyang";+$l['timezone_gmt_875'] = "(GMT +8:45) Eucla"; $l['timezone_gmt_900'] = "(GMT +9:00) Osaka, Sapporo, Seoul, Tokyo, Irkutsk"; $l['timezone_gmt_950'] = "(GMT +9:30) Adelaide, Darwin"; $l['timezone_gmt_1000'] = "(GMT +10:00) Melbourne, Papua New Guinea, Sydney, Yakutsk"; $l['timezone_gmt_1050'] = "(GMT +10:30) Lord Howe Island"; $l['timezone_gmt_1100'] = "(GMT +11:00) Magadan, New Caledonia, Solomon Islands, Vladivostok"; $l['timezone_gmt_1150'] = "(GMT +11:30) Norfolk Island";-$l['timezone_gmt_1200'] = "(GMT +12:00) Auckland, Wellington, Fiji, Marshall Island";+$l['timezone_gmt_1200'] = "(GMT +12:00) Auckland, Wellington, Fiji, Marshall Islands"; $l['timezone_gmt_1275'] = "(GMT +12:45) Chatham Islands"; $l['timezone_gmt_1300'] = "(GMT +13:00) Samoa, Tonga, Tokelau"; $l['timezone_gmt_1400'] = "(GMT +14:00) Line Islands";
Vulnerability Existed: no No Security Vulnerabilities Detected - [File Content/Localization Update] - inc/languages/english/admin/global.lang.php Old Code: ```php $l['off'] = "Off"; $l['alt_enabled'] = "Enabled"; $l['alt_disabled'] = "Disabled"; $l['saved'] = 'Saved'; ... $l['timezone_gmt_minus_1200'] = "(GMT -12:00) Marshall Islands"; ... $l['timezone_gmt_800'] = "(GMT +8:00) Beijing, Hong Kong, Perth, Singapore, Taipei, Manila"; $l['timezone_gmt_900'] = "(GMT +9:00) Osaka, Sapporo, Seoul, Tokyo, Irkutsk"; ... $l['timezone_gmt_1200'] = "(GMT +12:00) Auckland, Wellington, Fiji, Marshall Island"; ``` Fixed Code: ```php $l['off'] = "Off"; $l['alt_enabled'] = "Enabled"; $l['alt_disabled'] = "Disabled"; $l['enable'] = "Enable"; $l['disable'] = "Disable"; $l['saved'] = 'Saved'; ... $l['timezone_gmt_minus_1200'] = "(GMT -12:00) Howland and Baker Islands"; ... $l['timezone_gmt_800'] = "(GMT +8:00) Beijing, Hong Kong, Perth, Singapore, Taipei, Manila"; $l['timezone_gmt_850'] = "(GMT +8:30) Pyongyang"; $l['timezone_gmt_875'] = "(GMT +8:45) Eucla"; $l['timezone_gmt_900'] = "(GMT +9:00) Osaka, Sapporo, Seoul, Tokyo, Irkutsk"; ... $l['timezone_gmt_1200'] = "(GMT +12:00) Auckland, Wellington, Fiji, Marshall Islands"; ``` Explanation: This diff contains only localization and configuration string updates with no security implications. The changes include: 1. Adding two new language string entries (`enable` and `disable`) 2. Correcting timezone label descriptions (updating "Marshall Islands" to "Howland and Baker Islands" for GMT -12:00, adding missing timezone entries for GMT +8:30 and GMT +8:45, and fixing the plural form of "Marshall Island" to "Marshall Islands") These are purely cosmetic and informational updates to language strings and timezone labels. No code logic changes, no input validation issues, no injection vectors, and no security-relevant modifications are present. This is a safe localization update.
--- cache/mybb_mybb_1807/inc/languages/english/admin/home_dashboard.lang.php 2025-12-06 11:32:55.234129081 +0000+++ cache/mybb_mybb_1808/inc/languages/english/admin/home_dashboard.lang.php 2025-12-06 11:32:55.986177642 +0000@@ -36,7 +36,7 @@ $l['no_announcements'] = "No stored announcements. <a href=\"index.php?module=home&action=version_check\">Check for Updates</a>."; $l['your_version'] = "Your Version"; $l['latest_version'] = "Latest Version";-$l['update_forum'] = "Please upgrade to the latest version of MyBB by visiting the <a href=\"http://www.mybb.com\" target=\"_blank\">MyBB Website</a>.";+$l['update_forum'] = "Please upgrade to the latest version of MyBB by visiting the <a href=\"https://mybb.com\" target=\"_blank\">MyBB Website</a>."; $l['read_more'] = "Read more"; $l['success_up_to_date'] = "Congratulations, you are running the latest version of MyBB.";@@ -45,11 +45,10 @@ $l['error_communication'] = "There was a problem communicating with the version server. Please try again in a few minutes."; $l['error_fetch_news'] = "MyBB was unable to successfully fetch the latest announcements from the MyBB website."; -$l['news_description'] = "The latest news from the <a href=\"http://blog.mybb.com/\" target=\"_blank\">MyBB Blog</a>.";+$l['news_description'] = "The latest news from the <a href=\"https://blog.mybb.com/\" target=\"_blank\">MyBB Blog</a>."; $l['admin_notes_public'] = "These notes are public to all administrators."; $l['admin_notes'] = "Administrator Notes"; $l['save_notes'] = "Save Notes"; $l['success_notes_updated'] = "The administrator notes have been successfully updated.";-
Vulnerability Existed: no [CWE Name] - [CWE ID] - [File] [Lines] Not applicable - no vulnerability Fixed Code: Changed HTTP URLs to HTTPS for external links: - `http://www.mybb.com` → `https://mybb.com` - `http://blog.mybb.com/` → `https://blog.mybb.com/` Explanation: This diff contains only security improvements, not vulnerability fixes. The changes upgrade insecure HTTP protocol links to secure HTTPS protocol for external MyBB domains. This is a best practice enhancement to ensure encrypted communication and prevent man-in-the-middle attacks when users click these links. Additionally, the `www.` prefix was removed from the main domain URL (standard modern practice). There are no code vulnerabilities being fixed here—only protocol hardening and URL modernization. The removed blank line at the end is a formatting cleanup with no security implications.
--- cache/mybb_mybb_1807/inc/languages/english/admin/home_preferences.lang.php 2025-12-06 11:32:55.234129081 +0000+++ cache/mybb_mybb_1808/inc/languages/english/admin/home_preferences.lang.php 2025-12-06 11:32:55.986177642 +0000@@ -22,7 +22,7 @@ $l['success_preferences_updated'] = "The preferences have been successfully updated."; -$l['use_2fa_desc'] = "Two-Factor Authentication is a method to secure your admin account. After you've enabled it you'll see a QR Code below which you need to scan with an app <a href=\"http://docs.mybb.com/1.8/administration/security/2fa/\" target=\"_blank\">like Google Authenticator or Authy</a>. Those apps will generate a token which you need to enter on every acp login.";+$l['use_2fa_desc'] = "Two-Factor Authentication is a method to secure your admin account. After you've enabled it you'll see a QR Code below which you need to scan with an app <a href=\"https://docs.mybb.com/1.8/administration/security/2fa/\" target=\"_blank\">like Google Authenticator or Authy</a>. Those apps will generate a token which you need to enter on every acp login."; $l['my2fa_qr'] = "Two-Factor Authentication Code"; $l['recovery_codes_desc'] = "View your <a href=\"index.php?module=home-preferences&action=recovery_codes\">recovery codes</a>."; $l['recovery_codes'] = "Recovery Codes";
Vulnerability Existed: no [Insecure Transport (HTTP instead of HTTPS)] - [CWE-319] - inc/languages/english/admin/home_preferences.lang.php [25] [Old Code] $l['use_2fa_desc'] = "Two-Factor Authentication is a method to secure your admin account. After you've enabled it you'll see a QR Code below which you need to scan with an app <a href=\"http://docs.mybb.com/1.8/administration/security/2fa/\" target=\"_blank\">like Google Authenticator or Authy</a>. Those apps will generate a token which you need to enter on every acp login."; [Fixed Code] $l['use_2fa_desc'] = "Two-Factor Authentication is a method to secure your admin account. After you've enabled it you'll see a QR Code below which you need to scan with an app <a href=\"https://docs.mybb.com/1.8/administration/security/2fa/\" target=\"_blank\">like Google Authenticator or Authy</a>. Those apps will generate a token which you need to enter on every acp login."; Explanation: This change upgrades the documentation link from HTTP to HTTPS. While the old code used insecure HTTP transport, this was not a direct vulnerability in the application code itself since it's merely a reference link in documentation text. The fix properly addresses the best practice of using HTTPS for all external links, especially those pointing to security-related documentation. This prevents potential man-in-the-middle attacks on users accessing the documentation link and demonstrates security best practices.
--- cache/mybb_mybb_1807/inc/languages/english/admin/style_templates.lang.php 2025-12-06 11:32:55.234129081 +0000+++ cache/mybb_mybb_1808/inc/languages/english/admin/style_templates.lang.php 2025-12-06 11:32:55.986177642 +0000@@ -114,6 +114,7 @@ $l['group_footer'] = "Footer"; $l['group_video'] = "Video MyCode"; $l['group_sendthread'] = "Send Thread";+$l['group_mycode'] = "MyCode"; $l['expand'] = "Expand"; $l['collapse'] = "Collapse";
Vulnerability Existed: no No CWE/Vulnerability Identified Old Code: ``` $l['group_sendthread'] = "Send Thread"; $l['expand'] = "Expand"; ``` Fixed Code: ``` $l['group_sendthread'] = "Send Thread"; $l['group_mycode'] = "MyCode"; $l['expand'] = "Expand"; ``` Explanation: This diff shows the addition of a single language string definition (`$l['group_mycode'] = "MyCode";`) to a PHP language file. This is a benign localization/internationalization update with no security implications. The new line is simply assigning a static string value to an array key, which does not introduce any vulnerabilities such as injection, XSS, authentication bypass, or other security issues. Language definition files are not executable code and are isolated from user input processing.
--- cache/mybb_mybb_1807/inc/languages/english/admin/tools_adminlog.lang.php 2025-12-06 11:32:55.234129081 +0000+++ cache/mybb_mybb_1808/inc/languages/english/admin/tools_adminlog.lang.php 2025-12-06 11:32:55.986177642 +0000@@ -43,6 +43,7 @@ $l['admin_log_config_attachment_types_add'] = "Added attachment extension #{1} ({2})"; $l['admin_log_config_attachment_types_edit'] = "Edited attachment extension #{1} ({2})"; $l['admin_log_config_attachment_types_delete'] = "Deleted attachment extension #{1} ({2})";+$l['admin_log_config_attachment_types_toggle_status'] = "Toggled attachment status #{1} ({2})"; $l['admin_log_config_badwords_add'] = "Added word filter #{1} ({2})"; $l['admin_log_config_badwords_edit'] = "Edited word filter #{1} ({2})";@@ -106,6 +107,10 @@ $l['admin_log_config_questions_enable'] = "Enabled question #{1} ({2})"; $l['admin_log_config_questions_disable'] = "Disabled question #{1} ({2})"; +$l['admin_log_config_report_reasons_add'] = "Added report reason #{1} ({2})";+$l['admin_log_config_report_reasons_edit'] = "Edited report reason #{1} ({2})";+$l['admin_log_config_report_reasons_delete'] = "Deleted report reason #{1} ({2})";+ $l['admin_log_config_settings_delete_duplicates'] = "Deleted duplicate settings and setting groups"; $l['admin_log_config_settings_addgroup'] = "Added setting group #{1} ({2}) properties "; $l['admin_log_config_settings_editgroup'] = "Edited setting group #{1} ({2}) properties ";
Vulnerability Existed: no
No vulnerabilities detected - File is a language strings file
Explanation:
This diff adds new language string constants to a PHP language file used for admin logging messages. The changes are:
1. Addition of a new log message for toggling attachment status
2. Addition of three new log messages for report reason management (add, edit, delete)
These are static string definitions with no dynamic code execution, user input processing, or security-sensitive operations. The strings contain placeholders ({1}, {2}) which are safely interpolated by the application framework in a controlled manner. Language files of this type do not introduce vulnerabilities through string additions alone.
--- cache/mybb_mybb_1807/inc/languages/english/admin/tools_system_health.lang.php 2025-12-06 11:32:55.246129856 +0000+++ cache/mybb_mybb_1808/inc/languages/english/admin/tools_system_health.lang.php 2025-12-06 11:32:55.986177642 +0000@@ -74,7 +74,7 @@ $l['error_chmod'] = "of the required files and directories do not have proper CHMOD settings."; $l['error_invalid_table'] = "The specified table does not exist.";-$l['error_db_encoding_not_set'] = "Your current setup of MyBB is not setup to use this tool yet. Please see the <a href=\"http://docs.mybb.com/Utf8_setup.html\">MyBB Docs</a> for more information on how to set it up.";+$l['error_db_encoding_not_set'] = "Your current setup of MyBB is not setup to use this tool yet. Please see the <a href=\"https://docs.mybb.com/1.8/administration/utf-8-setup/\">MyBB Docs</a> for more information on how to set it up."; $l['error_not_supported'] = "Your current Database Engine is not supported by the UTF-8 Conversion Tool."; $l['error_invalid_input'] = "There was a problem checking the templates. Please try again or contact the MyBB Group for support."; $l['error_master_templates_altered'] = "The Master Templates have been altered. Please contact the MyBB Group for support on how to alter these.";
Vulnerability Existed: no Explanation: This diff shows a URL update in a language file string. The change updates a documentation link from `http://docs.mybb.com/Utf8_setup.html` to `https://docs.mybb.com/1.8/administration/utf-8-setup/`. This is not a security fix addressing a vulnerability—it's a maintenance update: - The URL is being updated to use HTTPS instead of HTTP (best practice for security, but not fixing an exploitable vulnerability in the code) - The URL path is being updated to point to current documentation - The change is in a language/string file, not executable code - No code logic is being altered Since this is a documentation URL update in a configuration string and not addressing an exploitable security vulnerability in the application code itself, there is no vulnerability to report using the requested format.
--- cache/mybb_mybb_1807/inc/languages/english/admin/tools_tasks.lang.php 2025-12-06 11:32:55.246129856 +0000+++ cache/mybb_mybb_1808/inc/languages/english/admin/tools_tasks.lang.php 2025-12-06 11:32:55.986177642 +0000@@ -71,6 +71,6 @@ $l['success_task_run'] = "The selected task has been run successfully."; $l['confirm_task_deletion'] = "Are you sure you wish to delete this scheduled task?";-$l['confirm_task_enable'] = "<strong>WARNING:</strong> You are about to enable a task that is only meant to be run via cron (Please see the <a href=\"http://docs.mybb.com/Help-Task_System.html\" target=\"_blank\">MyBB Docs</a> for more information). Continue?";+$l['confirm_task_enable'] = "<strong>WARNING:</strong> You are about to enable a task that is only meant to be run via cron (Please see the <a href=\"https://docs.mybb.com/1.8/administration/task-manager\" target=\"_blank\">MyBB Docs</a> for more information). Continue?"; $l['no_tasks'] = "There are no tasks on your forum at this time.";
Vulnerability Existed: no No Security Vulnerabilities Detected - [N/A] - inc/languages/english/admin/tools_tasks.lang.php [74] [Old Code] $l['confirm_task_enable'] = "<strong>WARNING:</strong> You are about to enable a task that is only meant to be run via cron (Please see the <a href=\"http://docs.mybb.com/Help-Task_System.html\" target=\"_blank\">MyBB Docs</a> for more information). Continue?"; [Fixed Code] $l['confirm_task_enable'] = "<strong>WARNING:</strong> You are about to enable a task that is only meant to be run via cron (Please see the <a href=\"https://docs.mybb.com/1.8/administration/task-manager\" target=\"_blank\">MyBB Docs</a> for more information). Continue?"; Explanation: This change updates a documentation URL in a language string from `http://docs.mybb.com/Help-Task_System.html` to `https://docs.mybb.com/1.8/administration/task-manager`. This is a non-security change that: 1. Upgrades the protocol from HTTP to HTTPS (security improvement via encrypted transport, but the original was in a help text/documentation link, not processing sensitive data) 2. Updates the documentation link path to a newer URL 3. Does not involve any code execution, input validation, authentication, or data handling changes The change is purely informational (a language/documentation string) with no security implications. There are no vulnerabilities being fixed or introduced.
--- cache/mybb_mybb_1807/inc/languages/english/admin/user_banning.lang.php 2025-12-06 11:32:55.246129856 +0000+++ cache/mybb_mybb_1808/inc/languages/english/admin/user_banning.lang.php 2025-12-06 11:32:55.986177642 +0000@@ -60,4 +60,3 @@ // Buttons $l['ban_user'] = "Ban User"; $l['update_ban'] = "Update Ban";-
Vulnerability Existed: no No Security Vulnerability - [File] inc/languages/english/admin/user_banning.lang.php [Line 63] Old Code: ``` $l['update_ban'] = "Update Ban"; ``` Fixed Code: ``` $l['update_ban'] = "Update Ban"; ``` Explanation: This diff removes trailing whitespace at the end of the file. This is a formatting/style change, not a security fix. The file contains only language string definitions with no executable code, user input handling, or security-sensitive operations. Removing trailing whitespace does not address, introduce, or relate to any security vulnerabilities (CWE, OWASP, etc.). This is routine code cleanup.
--- cache/mybb_mybb_1807/inc/languages/english/admin/user_groups.lang.php 2025-12-06 11:32:55.246129856 +0000+++ cache/mybb_mybb_1808/inc/languages/english/admin/user_groups.lang.php 2025-12-06 11:32:55.986177642 +0000@@ -154,7 +154,7 @@ $l['max_reputations_daily'] = "Maximum Reputations Allowed Per Day:"; $l['max_reputations_daily_desc'] = "Here you can enter the maximum number of reputations that users in this group can give per day. To allow unlimited reputations per day, enter 0."; $l['max_reputations_perthread'] = "Maximum Reputations Allowed Per Thread:";-$l['max_reputations_perthread_desc'] = "When 'Allow Post Reputation' is allowed, you can set the maximum amount of reputations that users in this group can give to the same user, in the same thread, in the box below. To allow unlimited reputations for a user, per thread, enter 0.";+$l['max_reputations_perthread_desc'] = "When 'Allow Post Reputation' is allowed, you can set the maximum amount of reputations that users in this group can give to the same user, in the same thread, per day, in the box below. To allow unlimited reputations for a user, per thread, enter 0."; $l['max_reputations_peruser'] = "Maximum Reputations Allowed Per User:"; $l['max_reputations_peruser_desc'] = "Along with a per thread maximum, you can enter a maximum number of reputations that users in this group can give to the same user per day. To allow unlimited reputations for a user, enter 0."; $l['warning_system'] = "Warning System";
Vulnerability Existed: no No CWE - N/A - inc/languages/english/admin/user_groups.lang.php [157] Old Code: ``` $l['max_reputations_perthread_desc'] = "When 'Allow Post Reputation' is allowed, you can set the maximum amount of reputations that users in this group can give to the same user, in the same thread, in the box below. To allow unlimited reputations for a user, per thread, enter 0."; ``` Fixed Code: ``` $l['max_reputations_perthread_desc'] = "When 'Allow Post Reputation' is allowed, you can set the maximum amount of reputations that users in this group can give to the same user, in the same thread, per day, in the box below. To allow unlimited reputations for a user, per thread, enter 0."; ``` Explanation: This is a documentation/string update that clarifies the behavior of the reputation system setting. The change adds "per day" to the description to better explain the functionality. Since this is a language string file containing only user-facing text and no executable code, there are no security vulnerabilities introduced or fixed by this change. The modification is purely informational and does not affect code execution, data handling, or security boundaries.
--- cache/mybb_mybb_1807/inc/languages/english/datahandler_user.lang.php 2025-12-06 11:32:55.246129856 +0000+++ cache/mybb_mybb_1808/inc/languages/english/datahandler_user.lang.php 2025-12-06 11:32:55.990177901 +0000@@ -42,3 +42,8 @@ $l['userdata_invalid_postnum'] = "The post count you entered is invalid. Please enter a valid post count, or leave the field empty."; $l['userdata_invalid_threadnum'] = "The thread count you entered is invalid. Please enter a valid thread count, or leave the field empty."; +$l['userdata_too_many_sig_images'] = "We are sorry, but we cannot update your signature because it contains too many images. Please remove some images from your signature to continue.";+$l['userdata_too_many_sig_images2'] = "<strong>Note:</strong> The maximum amount of images for signatures is {1}.";+$l['userdata_sig_too_long'] = "You cannot update your signature because it is too long. The maximum length for signatures is {1} characters. ";+$l['userdata_sig_remove_chars_plural'] = "Please remove {1} characters and try again.";+$l['userdata_sig_remove_chars_singular'] = "Please remove 1 character and try again.";
Vulnerability Existed: no
Explanation:
This diff shows additions to a language file (`inc/languages/english/datahandler_user.lang.php`) containing only localized string definitions. The changes add new language strings for user signature validation messages (maximum image count, length limits, and character removal prompts).
Since this file contains only static string definitions with no executable code, variable interpolation, database queries, or dynamic functionality, there are no security vulnerabilities introduced or fixed. The strings use placeholder syntax (`{1}`) which is standard for localization frameworks and is safe when properly handled by the application's string substitution logic elsewhere in the codebase.
These are purely informational messages presented to end users and pose no security risk.
--- cache/mybb_mybb_1807/inc/languages/english/forumdisplay.lang.php 2025-12-06 11:32:55.250130115 +0000+++ cache/mybb_mybb_1808/inc/languages/english/forumdisplay.lang.php 2025-12-06 11:32:55.990177901 +0000@@ -70,7 +70,7 @@ $l['clear'] = "Clear"; $l['sub_forums_in'] = "Forums in '{1}'"; $l['forum_rules'] = "{1} - Rules";-$l['subforums'] = "<strong>Sub Forums:</strong>";+$l['subforums'] = "Sub Forums:"; $l['asc'] = "asc"; $l['desc'] = "desc"; $l['forum_announcements'] = "Forum Announcements";
Vulnerability Existed: no Explanation: This diff shows a change to a language/localization string in MyBB forum software. The modification removes HTML `<strong>` tags from the string value, changing from `"<strong>Sub Forums:</strong>"` to `"Sub Forums:"`. This is not a security fix addressing a vulnerability. The change is a cosmetic/styling modification to a localization constant. The removal of HTML tags from a static string does not fix any security issue—the string was always safe as it's defined as a literal in the language file with no user input, variable interpolation, or dynamic content. This appears to be either: - A style preference change (removing bold formatting) - Preparation for CSS-based styling instead of inline HTML - A localization content update No security vulnerability existed in the original code, and no security fix was applied.
--- cache/mybb_mybb_1807/inc/languages/english/global.lang.php 2025-12-06 11:32:55.250130115 +0000+++ cache/mybb_mybb_1808/inc/languages/english/global.lang.php 2025-12-06 11:32:55.990177901 +0000@@ -429,7 +429,7 @@ $l['captcha_fetch_failure'] = 'There was an error fetching the new captcha.'; $l['question_fetch_failure'] = 'There was an error fetching the new question.'; -$l['timezone_gmt_minus_1200'] = "(GMT -12:00) Marshall Islands";+$l['timezone_gmt_minus_1200'] = "(GMT -12:00) Howland and Baker Islands"; $l['timezone_gmt_minus_1100'] = "(GMT -11:00) Nome, Midway Island"; $l['timezone_gmt_minus_1000'] = "(GMT -10:00) Hawaii, Papeete"; $l['timezone_gmt_minus_950'] = "(GMT -9:30) Marquesas Islands";@@ -458,13 +458,15 @@ $l['timezone_gmt_650'] = "(GMT +6:30) Yangon"; $l['timezone_gmt_700'] = "(GMT +7:00) Bangkok, Hanoi, Jakarta"; $l['timezone_gmt_800'] = "(GMT +8:00) Beijing, Hong Kong, Perth, Singapore, Taipei, Manila";+$l['timezone_gmt_850'] = "(GMT +8:30) Pyongyang";+$l['timezone_gmt_875'] = "(GMT +8:45) Eucla"; $l['timezone_gmt_900'] = "(GMT +9:00) Osaka, Sapporo, Seoul, Tokyo, Irkutsk"; $l['timezone_gmt_950'] = "(GMT +9:30) Adelaide, Darwin"; $l['timezone_gmt_1000'] = "(GMT +10:00) Melbourne, Papua New Guinea, Sydney, Yakutsk"; $l['timezone_gmt_1050'] = "(GMT +10:30) Lord Howe Island"; $l['timezone_gmt_1100'] = "(GMT +11:00) Magadan, New Caledonia, Solomon Islands, Vladivostok"; $l['timezone_gmt_1150'] = "(GMT +11:30) Norfolk Island";-$l['timezone_gmt_1200'] = "(GMT +12:00) Auckland, Wellington, Fiji, Marshall Island";+$l['timezone_gmt_1200'] = "(GMT +12:00) Auckland, Wellington, Fiji, Marshall Islands"; $l['timezone_gmt_1275'] = "(GMT +12:45) Chatham Islands"; $l['timezone_gmt_1300'] = "(GMT +13:00) Samoa, Tonga, Tokelau"; $l['timezone_gmt_1400'] = "(GMT +14:00) Line Islands";
``` Vulnerability Existed: no No security vulnerabilities detected Explanation: This diff contains only localization string updates to timezone descriptions in a language file. The changes are: 1. Corrected timezone label from "Marshall Islands" to "Howland and Baker Islands" for GMT -12:00 2. Added two new timezone entries (GMT +8:30 Pyongyang and GMT +8:45 Eucla) 3. Fixed grammar: "Marshall Island" → "Marshall Islands" for GMT +12:00 These are purely content/localization corrections with no code logic changes. String values in language files do not introduce security vulnerabilities. The changes do not involve user input handling, data processing, authentication, authorization, or any code execution paths. ```
--- cache/mybb_mybb_1807/inc/languages/english/index.lang.php 2025-12-06 11:32:55.250130115 +0000+++ cache/mybb_mybb_1808/inc/languages/english/index.lang.php 2025-12-06 11:32:55.990177901 +0000@@ -38,4 +38,4 @@ $l['online_guest_plural'] = "guests"; $l['online_guest_singular'] = "guest"; $l['online_note'] = "{1} {2} active in the past {3} minutes ({4} {5}, {6} of whom {7} invisible, and {8} {9}).";-$l['subforums'] = "<strong>Sub Forums:</strong>";+$l['subforums'] = "Sub Forums:";
Vulnerability Existed: no [No Vulnerability] - [N/A] - inc/languages/english/index.lang.php [41] Old Code: ```php $l['subforums'] = "<strong>Sub Forums:</strong>"; ``` Fixed Code: ```php $l['subforums'] = "Sub Forums:"; ``` Explanation: This change removes HTML markup (`<strong>` tags) from a language string definition. This is not a security fix but rather a refactoring change that moves presentation logic from the language file to the template layer. The original code was not vulnerable—storing HTML in language strings is a common practice in templating systems. The change appears to be a design improvement to separate content from presentation, not a security vulnerability fix. No CWE applies to this modification.
--- cache/mybb_mybb_1807/inc/languages/english/misc.lang.php 2025-12-06 11:32:55.250130115 +0000+++ cache/mybb_mybb_1808/inc/languages/english/misc.lang.php 2025-12-06 11:32:55.990177901 +0000@@ -58,6 +58,7 @@ $l['abbreviation'] = "Abbreviation"; $l['click_to_add'] = "Click a smilie to insert it into your message"; $l['close_window'] = "close window";+$l['no_smilies'] = "There are currently no smilies available."; $l['who_posted'] = "Who Posted?"; $l['total_posts'] = "Total Posts:";
Vulnerability Existed: no No Vulnerabilities Detected - [N/A] - inc/languages/english/misc.lang.php [61] Old Code: ``` $l['close_window'] = "close window"; ``` Fixed Code: ``` $l['close_window'] = "close window"; $l['no_smilies'] = "There are currently no smilies available."; ``` Explanation: This diff adds a new language string variable to a language file. The change is a simple addition of a new localized string constant with no user input, dynamic concatenation, or execution. The variable is assigned a static string literal in a read-only configuration/language file. No security vulnerability exists in this change. This is a safe, benign addition to support UI localization for a missing smilies scenario.
--- cache/mybb_mybb_1807/inc/languages/english/moderation.lang.php 2025-12-06 11:32:55.250130115 +0000+++ cache/mybb_mybb_1808/inc/languages/english/moderation.lang.php 2025-12-06 11:32:55.990177901 +0000@@ -148,7 +148,7 @@ $l['purgespammer'] = "Purge Spammer"; $l['purgespammer_purge'] = "Purge spammer {1}";-$l['purgespammer_purge_desc'] = "This will delete user's whole content (posts, private messages, events, etc.) and {1} him.";+$l['purgespammer_purge_desc'] = "This will delete user's whole content (posts, private messages, events, etc.) and {1} them."; $l['purgespammer_ban'] = "ban"; $l['purgespammer_delete'] = "delete"; $l['purgespammer_submit'] = "Purge Spammer";
Vulnerability Existed: no
No Security Vulnerability - Language String Update - inc/languages/english/moderation.lang.php [151]
Old Code:
```php
$l['purgespammer_purge_desc'] = "This will delete user's whole content (posts, private messages, events, etc.) and {1} him.";
```
Fixed Code:
```php
$l['purgespammer_purge_desc'] = "This will delete user's whole content (posts, private messages, events, etc.) and {1} them.";
```
Explanation:
This change is a grammar/language correction, not a security fix. The modification changes the pronoun from "him" to "them" for inclusive language purposes. This is a language localization file containing user-facing strings with no security implications. The `{1}` placeholder is a template variable that will be replaced at runtime, and this change does not affect how that substitution occurs or introduce any vulnerabilities related to injection, access control, data exposure, or any other security concern.
--- cache/mybb_mybb_1807/inc/languages/english/report.lang.php 2025-12-06 11:32:55.250130115 +0000+++ cache/mybb_mybb_1808/inc/languages/english/report.lang.php 2025-12-06 11:32:55.990177901 +0000@@ -16,9 +16,9 @@ $l['report_reason_reputation'] = "Report Reputation"; // Content reasons+$l['report_reason_rules'] = "Breaks Forum Rules"; $l['report_reason_bad'] = "Inappropriate Content"; $l['report_reason_spam'] = "Spam Content";-$l['report_reason_rules'] = "Breaks Forum Rules"; $l['report_reason_wrong'] = "Wrong Forum"; $l['report_reason_other'] = "Other"; @@ -26,5 +26,7 @@ $l['error_report_length'] = "Please provide a detailed reason for your report."; $l['error_invalid_report'] = "This content either does not exist or is not able to be reported.";+$l['error_invalid_report_reason'] = "The selected reason is invalid.";+$l['error_comment_required'] = "An additional comment is required for the selected reason."; $l['error_report_duplicate'] = "This content has already been reported by another member.<br />You may also report this content below.";-$l['report_reason_other_description'] = "If 'Other' please provide a reason for reporting this content.";+$l['report_reason_other_description'] = "Please provide more information about why you are reporting this content.";
Vulnerability Existed: no No vulnerabilities detected Explanation: This diff contains only language string updates to a MyBB forum language file. The changes are: 1. Reordering of report reason language variables (lines 19-23) 2. Adding two new error message language strings (lines 29-30) 3. Updating the description text for the "Other" reason (line 32) All changes are simple string assignments to language array variables with no dynamic code execution, variable interpolation, or user input handling. There are no SQL queries, file operations, or security-sensitive functions involved. Language files in MyBB are static translation resources and do not introduce vulnerabilities through reordering or adding new message strings.
--- cache/mybb_mybb_1807/inc/languages/english/usercp.lang.php 2025-12-06 11:32:55.250130115 +0000+++ cache/mybb_mybb_1808/inc/languages/english/usercp.lang.php 2025-12-06 11:32:55.994178160 +0000@@ -238,11 +238,6 @@ $l['draft_options'] = "Draft Options"; $l['selected_drafts_deleted'] = "The selected drafts have been deleted.<br />You will be now taken back to the drafts listing."; $l['no_drafts_selected'] = "You did not select any drafts to delete";-$l['too_many_sig_images'] = "We are sorry, but we cannot update your signature because it contains too many images. Please remove some images from your signature to continue.";-$l['too_many_sig_images2'] = "<strong>Note:</strong> The maximum amount of images for signatures is {1}.";-$l['sig_too_long'] = "You cannot update your signature because it is too long. The maximum length for signatures is {1} characters. ";-$l['sig_remove_chars_plural'] = "Please remove {1} characters and try again.";-$l['sig_remove_chars_singular'] = "Please remove 1 character and try again."; $l['group_memberships'] = "Group Memberships"; $l['not_member_of_group'] = "Sorry, you cannot perform that action because you are currently not a member of that group."; $l['cannot_set_displaygroup'] = "This group cannot be set as a display group.";@@ -422,4 +417,3 @@ $l['buddyrequest_declined'] = 'The selected buddy request has been declined.'; $l['user_doesnt_exist'] = 'The end user no longer exists.'; $l['buddyrequests_sent_success'] = 'Buddy requests sent successfully.';-
Vulnerability Existed: no
No Security Vulnerabilities Detected - [N/A] - inc/languages/english/usercp.lang.php [241-245]
Old Code:
```php
$l['too_many_sig_images'] = "We are sorry, but we cannot update your signature because it contains too many images. Please remove some images from your signature to continue.";
$l['too_many_sig_images2'] = "<strong>Note:</strong> The maximum amount of images for signatures is {1}.";
$l['sig_too_long'] = "You cannot update your signature because it is too long. The maximum length for signatures is {1} characters. ";
$l['sig_remove_chars_plural'] = "Please remove {1} characters and try again.";
$l['sig_remove_chars_singular'] = "Please remove 1 character and try again.";
```
Fixed Code:
```php
(lines removed)
```
Explanation:
This diff shows the removal of 5 language string definitions from a MyBB language file. These are simple string constants used for user-facing error messages in the user control panel. The removal of these strings does not introduce or fix any security vulnerabilities. This appears to be a code cleanup or feature removal (likely signature validation messages are no longer needed or have been refactored). The strings themselves contained no injectable code or unsafe operations—they were static language definitions with placeholder tokens ({1}). The trailing blank line removal at the end of the file is also not a security issue. No vulnerability is present.
--- cache/mybb_mybb_1807/inc/mailhandlers/php.php 2025-12-06 11:32:55.250130115 +0000+++ cache/mybb_mybb_1808/inc/mailhandlers/php.php 2025-12-06 11:32:55.994178160 +0000@@ -51,7 +51,7 @@ @ini_set("sendmail_from", $mybb->settings['adminemail']); } - $dir = "/{$config['admin_dir']}/";+ $dir = "/{$mybb->config['admin_dir']}/"; $pos = strrpos($_SERVER['PHP_SELF'], $dir); if(defined('IN_ADMINCP') && $pos !== false) {
Vulnerability Existed: no
[No Vulnerability - Configuration Access Fix] - [N/A] - [inc/mailhandlers/php.php] [Lines 54]
Old Code:
```php
$dir = "/{$config['admin_dir']}/";
```
Fixed Code:
```php
$dir = "/{$mybb->config['admin_dir']}/";
```
Explanation:
This change is a bug fix, not a security vulnerability fix. The old code references `$config['admin_dir']`, which appears to be an undefined variable in this scope. The fixed code correctly accesses the configuration through `$mybb->config['admin_dir']`, which is the proper way to access the MyBB configuration object. This ensures the correct variable is used and prevents potential undefined variable notices/warnings, but it does not fix an existing security vulnerability. The change improves code correctness and reliability by ensuring the admin directory path is retrieved from the proper configuration source.
--- cache/mybb_mybb_1807/inc/plugins/hello.php 2025-12-06 11:32:55.250130115 +0000+++ cache/mybb_mybb_1808/inc/plugins/hello.php 2025-12-06 11:32:55.998178417 +0000@@ -13,7 +13,7 @@ { die('This file cannot be accessed directly.'); }- + // cache templates - this is important when it comes to performance // THIS_SCRIPT is defined by some of the MyBB scripts, including index.php if(defined('THIS_SCRIPT'))@@ -74,9 +74,9 @@ return array( 'name' => 'Hello World!', 'description' => $lang->hello_desc,- 'website' => 'http://mybb.com',+ 'website' => 'https://mybb.com', 'author' => 'MyBB Group',- 'authorsite' => 'http://www.mybb.com',+ 'authorsite' => 'https://mybb.com', 'version' => '2.0', 'compatibility' => '18*', 'codename' => 'hello'@@ -318,13 +318,13 @@ // Delete deprecated entries. $db->delete_query('settings', "gid='{$gid}' AND description='HELLODELETEMARKER'");- + // This is required so it updates the settings.php file as well and not only the database - they must be synchronized! rebuild_settings(); // Include this file because it is where find_replace_templatesets is defined require_once MYBB_ROOT.'inc/adminfunctions_templates.php';- + // Edit the index template and add our variable to above {$forums} find_replace_templatesets('index', '#'.preg_quote('{$forums}').'#', "{\$hello}\n{\$forums}"); }@@ -339,7 +339,7 @@ function hello_deactivate() { require_once MYBB_ROOT.'inc/adminfunctions_templates.php';- + // remove template edits find_replace_templatesets('index', '#'.preg_quote('{$hello}').'#', ''); }@@ -584,4 +584,4 @@ // Redirect to index.php with a message redirect('index.php', $lang->hello_done);-}\ No newline at end of file+}
Vulnerability Existed: no HTTPS Protocol Upgrade - CWE-295 (Improper Certificate Validation) - inc/plugins/hello.php (Lines 77, 79) Old Code: ``` 'website' => 'http://mybb.com', 'authorsite' => 'http://www.mybb.com', ``` Fixed Code: ``` 'website' => 'https://mybb.com', 'authorsite' => 'https://mybb.com', ``` Explanation: This change upgrades HTTP URLs to HTTPS, which is a security improvement rather than a vulnerability fix. The original code was not inherently vulnerable - it was simply using unencrypted URLs for plugin metadata. The fix enhances security by ensuring encrypted communication and preventing man-in-the-middle attacks when accessing these URLs. Additionally, the 'authorsite' URL was corrected to match the canonical domain (removing the 'www.' subdomain). Additional Changes (Non-Security): The diff also includes whitespace normalization (trailing whitespace removal on lines 16, 321, 327, and 342, and adding a newline at EOF on line 587), which are code formatting improvements with no security implications.
--- cache/mybb_mybb_1807/inc/tasks/versioncheck.php 2025-12-06 11:32:55.250130115 +0000+++ cache/mybb_mybb_1808/inc/tasks/versioncheck.php 2025-12-06 11:32:55.998178417 +0000@@ -20,7 +20,7 @@ // Check for the latest version require_once MYBB_ROOT.'inc/class_xml.php';- $contents = fetch_remote_file("http://www.mybb.com/version_check.php");+ $contents = fetch_remote_file("https://mybb.com/version_check.php"); if(!$contents) {
Vulnerability Existed: yes
TRUE POSITIVE
Insecure Transport Protocol - CWE-319 - inc/tasks/versioncheck.php [23]
[Old Code]
$contents = fetch_remote_file("http://www.mybb.com/version_check.php");
[Fixed Code]
$contents = fetch_remote_file("https://mybb.com/version_check.php");
Explanation:
The original code used an unencrypted HTTP connection to fetch version check information from mybb.com. This is vulnerable to man-in-the-middle (MITM) attacks where an attacker could intercept the connection and either eavesdrop on the data or inject malicious version information. The fix upgrades the connection to HTTPS, which provides encryption and authentication, preventing unauthorized interception and tampering of the version check data. This is particularly critical for version checking functionality since attackers could potentially inject false version information to mislead users about available security updates.
--- cache/mybb_mybb_1807/index.php 2025-12-06 11:32:55.250130115 +0000+++ cache/mybb_mybb_1808/index.php 2025-12-06 11:32:55.998178417 +0000@@ -100,7 +100,7 @@ } // Properly format the username and assign the template.- $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']);+ $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); $user['profilelink'] = build_profile_link($user['username'], $user['uid']); eval('$onlinemembers .= "'.$templates->get('index_whosonline_memberbit', 1, 0).'";'); $comma = $lang->comma;@@ -241,7 +241,7 @@ $age = ' ('.($year - $bday['2']).')'; } - $bdayuser['username'] = format_name($bdayuser['username'], $bdayuser['usergroup'], $bdayuser['displaygroup']);+ $bdayuser['username'] = format_name(htmlspecialchars_uni($bdayuser['username']), $bdayuser['usergroup'], $bdayuser['displaygroup']); $bdayuser['profilelink'] = build_profile_link($bdayuser['username'], $bdayuser['uid']); eval('$bdays .= "'.$templates->get('index_birthdays_birthday', 1, 0).'";'); ++$bdaycount;
Vulnerability Existed: yes TRUE POSITIVE Cross-Site Scripting (XSS) - CWE-79 - index.php Lines 103, 244 Old Code: ```php $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']); ``` ```php $bdayuser['username'] = format_name($bdayuser['username'], $bdayuser['usergroup'], $bdayuser['displaygroup']); ``` Fixed Code: ```php $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); ``` ```php $bdayuser['username'] = format_name(htmlspecialchars_uni($bdayuser['username']), $bdayuser['usergroup'], $bdayuser['displaygroup']); ``` Explanation: The vulnerability existed because usernames retrieved from the database were passed directly to `format_name()` without HTML escaping. Although usernames are typically stored data, when they are later inserted into template output via the `eval()` statement on lines 105 and 246, unescaped special characters or malicious HTML entities in the username could be interpreted as HTML/JavaScript code. The fix properly escapes HTML special characters using `htmlspecialchars_uni()` before passing the username to `format_name()`, preventing XSS attacks where a username containing script tags or event handlers could execute arbitrary JavaScript in the context of other users' browsers viewing the index page.
--- cache/mybb_mybb_1807/install/index.php 2025-12-06 11:32:55.258130631 +0000+++ cache/mybb_mybb_1808/install/index.php 2025-12-06 11:32:56.002178676 +0000@@ -67,7 +67,7 @@ // Include the necessary constants for installation $grouppermignore = array('gid', 'type', 'title', 'description', 'namestyle', 'usertitle', 'stars', 'starimage', 'image');-$groupzerogreater = array('pmquota', 'maxpmrecipients', 'maxreputationsday', 'attachquota', 'maxemails', 'maxwarningsday', 'maxposts', 'edittimelimit', 'canusesigxposts', 'maxreputationsperthread');+$groupzerogreater = array('pmquota', 'maxpmrecipients', 'maxreputationsday', 'attachquota', 'maxemails', 'maxwarningsday', 'maxposts', 'edittimelimit', 'canusesigxposts', 'maxreputationsperuser', 'maxreputationsperthread', 'emailfloodtime'); $displaygroupfields = array('title', 'description', 'namestyle', 'usertitle', 'stars', 'starimage', 'image'); $fpermfields = array('canview', 'canviewthreads', 'candlattachments', 'canpostthreads', 'canpostreplys', 'canpostattachments', 'canratethreads', 'caneditposts', 'candeleteposts', 'candeletethreads', 'caneditattachments', 'canpostpolls', 'canvotepolls', 'cansearch', 'modposts', 'modthreads', 'modattachments', 'mod_edit_posts'); @@ -1493,7 +1493,7 @@ * * Please see the MyBB Docs for advanced * database configuration for larger installations- * http://docs.mybb.com/+ * https://docs.mybb.com/ */ \$config['database']['type'] = '{$mybb->input['dbengine']}';@@ -1586,12 +1586,48 @@ 'promotion_logs' => 180 // Promotion logs ); +/**+ * Disallowed Remote Hosts+ * List of hosts the fetch_remote_file() function will not+ * perform requests to.+ * It is recommended that you enter hosts resolving to the+ * forum server here to prevent Server Side Request+ * Forgery attacks.+ */++\$config['disallowed_remote_hosts'] = array(+ 'localhost',+);++/**+ * Disallowed Remote Addresses+ * List of IPv4 addresses the fetch_remote_file() function+ * will not perform requests to.+ * It is recommended that you enter addresses resolving to+ * the forum server here to prevent Server Side Request+ * Forgery attacks.+ * Removing all values disables resolving hosts in that+ * function.+ */++\$config['disallowed_remote_addresses'] = array(+ '127.0.0.1',+ '10.0.0.0/8',+ '172.16.0.0/12',+ '192.168.0.0/16',+);+ "; $file = fopen(MYBB_ROOT.'inc/config.php', 'w'); fwrite($file, $configdata); fclose($file); + if(function_exists('opcache_invalidate'))+ {+ opcache_invalidate(MYBB_ROOT."inc/config.php");+ }+ // Error reporting back on $db->error_reporting = 1; @@ -2377,6 +2413,7 @@ $cache->update("plugins", array()); $cache->update("internal_settings", array('encryption_key' => random_str(32))); $cache->update_default_theme();+ $cache->update_reportreasons(true); $version_history = array(); $dh = opendir(INSTALL_ROOT."resources");
I'll analyze this code diff for security vulnerabilities.
Vulnerability Existed: yes
TRUE POSITIVE
**Server-Side Request Forgery (SSRF) - CWE-918** - install/index.php Lines 1599-1620
[Old Code]
```
No disallowed remote hosts/addresses configuration existed
```
[Fixed Code]
```php
$config['disallowed_remote_hosts'] = array(
'localhost',
);
$config['disallowed_remote_addresses'] = array(
'127.0.0.1',
'10.0.0.0/8',
'172.16.0.0/12',
'192.168.0.0/16',
);
```
Explanation:
The application previously lacked SSRF protections in the `fetch_remote_file()` function. This fix adds a whitelist of disallowed hosts and IP addresses (including private/reserved ranges and localhost) to prevent Server-Side Request Forgery attacks. An attacker could have exploited an unbounded `fetch_remote_file()` function to make requests to internal services, cloud metadata endpoints, or private networks. This is a critical security fix.
---
Vulnerability Existed: no
**Insecure Protocol - CWE-295** - install/index.php Line 1496
[Old Code]
```
* http://docs.mybb.com/
```
[Fixed Code]
```
* https://docs.mybb.com/
```
Explanation:
This is a documentation URL change from HTTP to HTTPS. While not a direct code vulnerability, this improves security posture by directing users to the HTTPS version of documentation, reducing risks of man-in-the-middle attacks on documentation retrieval.
---
Vulnerability Existed: no
**OpCache Invalidation** - install/index.php Lines 1627-1631
[Old Code]
```
No opcache invalidation after config file write
```
[Fixed Code]
```php
if(function_exists('opcache_invalidate'))
{
opcache_invalidate(MYBB_ROOT."inc/config.php");
}
```
Explanation:
This is a defensive fix rather than a vulnerability patch. It ensures that when the configuration file is updated during installation, the OpCache is invalidated to prevent serving stale cached bytecode. Without this, the server could serve outdated configuration from memory cache, potentially causing inconsistent behavior or security issues after updates.
---
Vulnerability Existed: not sure
**Data Initialization** - install/index.php Line 2416
[Old Code]
```
$cache->update_default_theme();
```
[Fixed Code]
```php
$cache->update_default_theme();
$cache->update_reportreasons(true);
```
Explanation:
An additional cache update call was added. Without seeing the implementation of `update_reportreasons()`, the security impact is unclear. However, initializing report reason cache during installation may prevent missing data issues that could lead to unexpected behavior or information disclosure vulnerabilities if report reasons are not properly initialized.
--- cache/mybb_mybb_1807/install/resources/language.lang.php 2025-12-06 11:32:55.258130631 +0000+++ cache/mybb_mybb_1808/install/resources/language.lang.php 2025-12-06 11:32:56.002178676 +0000@@ -58,7 +58,7 @@ $l['mybb_incorrect_folder'] = "<div class=\"border_wrapper upgrade_note\" style=\"padding: 4px;\"> <h3>MyBB has detected that it is running from the \"Upload\" directory.</h3>- <p>While there is nothing wrong with this, it is recommended that your upload the contents of the \"Upload\" directory and not the directory itself.<br /><br />For more information please see the <a href=\"http://docs.mybb.com/Help-Upload_Directory.html\" target=\"_blank\">MyBB Docs</a>.</p>+ <p>While there is nothing wrong with this, it is recommended that your upload the contents of the \"Upload\" directory and not the directory itself.<br /><br />For more information please see the <a href=\"https://docs.mybb.com/1.8/install/#uploading-files\" target=\"_blank\">MyBB Docs</a>.</p> </div>"; $l['welcome_step'] = '<p>Welcome to the installation wizard for MyBB {1}. This wizard will install and configure a copy of MyBB on your server.</p>@@ -74,7 +74,7 @@ </ul> <p>After each step has successfully been completed, click Next to move on to the next step.</p> <p>Click "Next" to view the MyBB license agreement.</p>-<p><input type="checkbox" name="allow_anonymous_info" value="1" id="allow_anonymous" checked="checked" /> <label for="allow_anonymous"> Send anonymous statistics about your server specifications to the MyBB Group</label> (<a href="http://docs.mybb.com/Anonymous_Statistics.html" style="color: #555;" target="_blank"><small>What information is sent?</small></a>)</p>';+<p><input type="checkbox" name="allow_anonymous_info" value="1" id="allow_anonymous" checked="checked" /> <label for="allow_anonymous"> Send anonymous statistics about your server specifications to the MyBB Group</label> (<a href="https://docs.mybb.com/1.8/install/anonymous-statistics/" style="color: #555;" target="_blank"><small>What information is sent?</small></a>)</p>'; $l['license_step'] = '<div class="license_agreement"> {1}@@ -141,13 +141,13 @@ $l['req_step_error_phpversion'] = 'MyBB Requires PHP 5.2.0 or later to run. You currently have {1} installed.'; $l['req_step_error_dboptions'] = 'MyBB requires one or more suitable database extensions to be installed. Your server reported that none were available.'; $l['req_step_error_xmlsupport'] = 'MyBB requires PHP to be compiled with support for XML Data Handling. Please see <a href="http://www.php.net/xml" target="_blank">PHP.net</a> for more information.';-$l['req_step_error_configdefaultfile'] = 'The configuration file (inc/config.default.php) could not be renamed. Please manually rename the <u>config.default.php</u> file to <u>config.php</u> to allow it to be written to or contact <a href="http://www.mybb.com/support" target="_blank">MyBB Support.</a>';-$l['req_step_error_configfile'] = 'The configuration file (inc/config.php) is not writable. Please adjust the <a href="http://docs.mybb.com/CHMOD_Files.html" target="_blank">chmod</a> permissions to allow it to be written to.';-$l['req_step_error_settingsfile'] = 'The settings file (inc/settings.php) is not writable. Please adjust the <a href="http://docs.mybb.com/CHMOD_Files.html" target="_blank">chmod</a> permissions to allow it to be written to.';-$l['req_step_error_cachedir'] = 'The cache directory (cache/) is not writable. Please adjust the <a href="http://docs.mybb.com/CHMOD_Files.html" target="_blank">chmod</a> permissions to allow it to be written to.';-$l['req_step_error_uploaddir'] = 'The uploads directory (uploads/) is not writable. Please adjust the <a href="http://docs.mybb.com/CHMOD_Files.html" target="_blank">chmod</a> permissions to allow it to be written to.';-$l['req_step_error_avatardir'] = 'The avatars directory (uploads/avatars/) is not writable. Please adjust the <a href="http://docs.mybb.com/CHMOD_Files.html" target="_blank">chmod</a> permissions to allow it to be written to.';-$l['req_step_error_cssddir'] = 'The css directory (css/) is not writable. Please adjust the <a href="http://docs.mybb.com/CHMOD_Files.html" target="_blank">chmod</a> permissions to allow it to be written to.';+$l['req_step_error_configdefaultfile'] = 'The configuration file (inc/config.default.php) could not be renamed. Please manually rename the <u>config.default.php</u> file to <u>config.php</u> to allow it to be written to or contact <a href="https://mybb.com/support" target="_blank">MyBB Support.</a>';+$l['req_step_error_configfile'] = 'The configuration file (inc/config.php) is not writable. Please adjust the <a href="https://docs.mybb.com/1.8/administration/security/file-permissions" target="_blank">chmod</a> permissions to allow it to be written to.';+$l['req_step_error_settingsfile'] = 'The settings file (inc/settings.php) is not writable. Please adjust the <a href="https://docs.mybb.com/1.8/administration/security/file-permissions" target="_blank">chmod</a> permissions to allow it to be written to.';+$l['req_step_error_cachedir'] = 'The cache directory (cache/) is not writable. Please adjust the <a href="https://docs.mybb.com/1.8/administration/security/file-permissions" target="_blank">chmod</a> permissions to allow it to be written to.';+$l['req_step_error_uploaddir'] = 'The uploads directory (uploads/) is not writable. Please adjust the <a href="https://docs.mybb.com/1.8/administration/security/file-permissions" target="_blank">chmod</a> permissions to allow it to be written to.';+$l['req_step_error_avatardir'] = 'The avatars directory (uploads/avatars/) is not writable. Please adjust the <a href="https://docs.mybb.com/1.8/administration/security/file-permissions" target="_blank">chmod</a> permissions to allow it to be written to.';+$l['req_step_error_cssddir'] = 'The css directory (css/) is not writable. Please adjust the <a href="https://docs.mybb.com/1.8/administration/security/file-permissions" target="_blank">chmod</a> permissions to allow it to be written to.'; $l['req_step_error_tablelist'] = '<div class="error"> <h3>Error</h3> <p>The MyBB Requirements check failed due to the reasons below. MyBB installation cannot continue because you did not meet the MyBB requirements. Please correct the errors below and try again:</p>@@ -238,7 +238,7 @@ <td class="last alt_col"><input type="text" class="text_input" name="websiteurl" id="websiteurl" value="{4}" /></td> </tr> <tr>- <th colspan="2" class="first last">Cookie settings <a title="What\'s this?" target="_blank" href="http://docs.mybb.com/Cookie_Settings.html">(?)</a></th>+ <th colspan="2" class="first last">Cookie settings <a title="What\'s this?" target="_blank" href="https://docs.mybb.com/1.8/development/cookies">(?)</a></th> </tr> <tr> <td class="first"><label for="cookiedomain">Cookie Domain:</label></td>@@ -335,10 +335,10 @@ $l['done_step_adminoptions'] = '<p>Building Administrator permissions...'; $l['done_step_cachebuilding'] = '<p>Building data caches...'; $l['done_step_success'] = '<p class="success">Your copy of MyBB has successfully been installed and configured correctly.</p>-<p>The MyBB Group thanks you for your support in installing our software and we hope to see you around the <a href="http://community.mybb.com/" target="_blank">Community Forums</a> if you need help or wish to become a part of the MyBB community.</p>';+<p>The MyBB Group thanks you for your support in installing our software and we hope to see you around the <a href="https://community.mybb.com/" target="_blank">Community Forums</a> if you need help or wish to become a part of the MyBB community.</p>'; $l['done_step_locked'] = '<p>Your installer has been locked. To unlock the installer please delete the \'lock\' file in this directory.</p><p>You may now proceed to your new copy of <a href="../index.php">MyBB</a> or its <a href="../admin/index.php">Admin Control Panel</a>.</p>'; $l['done_step_dirdelete'] = '<p><strong><span style="color:red">Please remove this directory before exploring your copy of MyBB.</span></strong></p>';-$l['done_whats_next'] = '<div class="error"><p><strong>Switching from another forum software?</strong></p><p>MyBB offers a merge system for easy merging of multiple forums from various different popular forum software, allowing an easy conversion process to MyBB. If you\'re looking to switch to MyBB, you\'re heading in the right direction! Check out the <a target="_blank" href="http://www.mybb.com/downloads/merge-system">Merge System</a> for more information.</p>';+$l['done_whats_next'] = '<div class="error"><p><strong>Switching from another forum software?</strong></p><p>MyBB offers a merge system for easy merging of multiple forums from various different popular forum software, allowing an easy conversion process to MyBB. If you\'re looking to switch to MyBB, you\'re heading in the right direction! Check out the <a target="_blank" href="https://mybb.com/downloads/merge-system">Merge System</a> for more information.</p>'; /* UPGRADE LANGUAGE VARIABLES */ $l['upgrade'] = "Upgrade Process";@@ -355,7 +355,7 @@ $l['upgrade_congrats'] = "<p>Congratulations, your copy of MyBB has successfully been updated to {1}.</p>{2}<p><strong>What's Next?</strong></p><ul><li>Please use the 'Find Updated Templates' tool in the Admin CP to find customized templates updated during this upgrade process. Edit them to contain the changes or revert them to originals.</li><li>Ensure that your board is still fully functional.</li></ul>"; $l['upgrade_template_reversion'] = "Template Reversion Warning"; $l['upgrade_template_reversion_success'] = "<p>All necessary database modifications have successfully been made to upgrade your board.</p><p>This upgrade requires all templates to be reverted to the new ones contained in the package so please back up any custom templates you have made before clicking next.";-$l['upgrade_send_stats'] = "<p><input type=\"checkbox\" name=\"allow_anonymous_info\" value=\"1\" id=\"allow_anonymous\" checked=\"checked\" /> <label for=\"allow_anonymous\"> Send anonymous statistics about your server specifications to the MyBB Group</label> (<a href=\"http://docs.mybb.com/Anonymous_Statistics.html\" style=\"color: #555;\" target=\"_blank\"><small>What information is sent?</small></a>)</p>";+$l['upgrade_send_stats'] = "<p><input type=\"checkbox\" name=\"allow_anonymous_info\" value=\"1\" id=\"allow_anonymous\" checked=\"checked\" /> <label for=\"allow_anonymous\"> Send anonymous statistics about your server specifications to the MyBB Group</label> (<a href=\"https://docs.mybb.com/1.8/install/anonymous-statistics/\" style=\"color: #555;\" target=\"_blank\"><small>What information is sent?</small></a>)</p>"; $l['please_login'] = "Please Login"; $l['login'] = "Login";@@ -368,6 +368,6 @@ $l['development_preview'] = "<div class=\"error\"><h2 class=\"fail\">Warning</h2><p>This version of MyBB is a development preview and is to be used for testing purposes only.</p><p>No official support, other than for plugins and theme development, will be provided for this version. By continuing with this install/upgrade you do so at your own risk.</p></div>"; $l['locked'] = 'The installer is currently locked, please remove \'lock\' from the install directory to continue'; $l['no_permision'] = "You do not have permissions to run this process. You need administrator permissions to be able to run the upgrade procedure.<br /><br />If you need to logout, please click <a href=\"upgrade.php?action=logout&logoutkey={1}\">here</a>. From there you will be able to log in again under your administrator account.";+$l['no_theme_functions_file'] = 'No theme functions file has been found. Make sure that all files are uploaded properly.'; $l['task_versioncheck_ran'] = "The version check task successfully ran.";-
I'll analyze this diff for security vulnerabilities. **Analysis Result:** Vulnerability Existed: **no** **Reason:** This diff contains only **HTTP to HTTPS URL upgrades** and the addition of a language variable. These are not security fixes for vulnerabilities in the code itself. **Details:** 1. **URL Protocol Changes (HTTP → HTTPS)**: Lines 61, 77, 144-149, 241, 338, 341, 358 - Changed URLs from `http://` to `https://` (docs.mybb.com, mybb.com, community.mybb.com) - This is a **security hardening practice**, not a fix for an existing vulnerability - HTTPS enforces encrypted communication, but the original code using HTTP wasn't vulnerable per se—it just lacked encryption 2. **Updated Documentation Links**: Multiple lines - URLs now point to more specific documentation paths (e.g., `https://docs.mybb.com/1.8/install/#uploading-files` instead of `http://docs.mybb.com/Help-Upload_Directory.html`) - No code logic changes, only link updates 3. **New Language Variable Added**: Line 371 - `$l['no_theme_functions_file']` - Simple string addition, no security impact **Conclusion:** This diff improves security practices through HTTPS enforcement but does not address any existing vulnerabilities in the code. There are no CWE violations being fixed here—this is maintenance and best-practice improvement.
--- cache/mybb_mybb_1807/install/resources/mysql_db_inserts.php 2025-12-06 11:32:55.266131148 +0000+++ cache/mybb_mybb_1808/install/resources/mysql_db_inserts.php 2025-12-06 11:32:56.002178676 +0000@@ -8,27 +8,27 @@ * */ -$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (1, 'ZIP File', 'application/zip', 'zip', 1024, 'images/attachtypes/zip.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (2, 'JPG Image', 'image/jpeg', 'jpg', 500, 'images/attachtypes/image.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (3, 'Text Document', 'text/plain', 'txt', 200, 'images/attachtypes/txt.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (4, 'GIF Image', 'image/gif', 'gif', 500, 'images/attachtypes/image.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (5, 'Adobe Photoshop File', 'application/x-photoshop', 'psd', 1024, 'images/attachtypes/psd.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (6, 'PHP File', 'application/x-httpd-php', 'php', 500, 'images/attachtypes/php.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (7, 'PNG Image', 'image/png', 'png', 500, 'images/attachtypes/image.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (8, 'Microsoft Word Document', 'application/msword', 'doc', 1024, 'images/attachtypes/doc.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (9, 'HTM File', 'text/html', 'htm', 100, 'images/attachtypes/html.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (10, 'HTML File', 'text/html', 'html', 100, 'images/attachtypes/html.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (11, 'JPEG Image', 'image/jpeg', 'jpeg', 500, 'images/attachtypes/image.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (12, 'GZIP Compressed File', 'application/x-gzip', 'gz', 1024, 'images/attachtypes/tar.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (13, 'TAR Compressed File', 'application/x-tar', 'tar', 1024, 'images/attachtypes/tar.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (14, 'CSS Stylesheet', 'text/css', 'css', 100, 'images/attachtypes/css.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (15, 'Adobe Acrobat PDF', 'application/pdf', 'pdf', 2048, 'images/attachtypes/pdf.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (16, 'Bitmap Image', 'image/bmp', 'bmp', 500, 'images/attachtypes/image.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (17, 'Microsoft Word 2007 Document', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'docx', 1024, 'images/attachtypes/doc.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (18, 'Microsoft Excel Document', 'application/vnd.ms-excel', 'xls', 1024, 'images/attachtypes/xls.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (19, 'Microsoft Excel 2007 Document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'xlsx', 1024, 'images/attachtypes/xls.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (20, 'Microsoft PowerPoint Document', 'application/vnd.ms-powerpoint', 'ppt', 1024, 'images/attachtypes/ppt.png');";-$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon) VALUES (21, 'Microsoft PowerPoint 2007 Document', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'pptx', 1024, 'images/attachtypes/ppt.png');";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (1, 'ZIP File', 'application/zip', 'zip', 1024, 'images/attachtypes/zip.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (2, 'JPG Image', 'image/jpeg', 'jpg', 500, 'images/attachtypes/image.png', 1, '-1', '-1', 1);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (3, 'Text Document', 'text/plain', 'txt', 200, 'images/attachtypes/txt.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (4, 'GIF Image', 'image/gif', 'gif', 500, 'images/attachtypes/image.png', 1, '-1', '-1', 1);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (5, 'Adobe Photoshop File', 'application/x-photoshop', 'psd', 1024, 'images/attachtypes/psd.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (6, 'PHP File', 'application/x-httpd-php', 'php', 500, 'images/attachtypes/php.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (7, 'PNG Image', 'image/png', 'png', 500, 'images/attachtypes/image.png', 1, '-1', '-1', 1);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (8, 'Microsoft Word Document', 'application/msword', 'doc', 1024, 'images/attachtypes/doc.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (9, 'HTM File', 'text/html', 'htm', 100, 'images/attachtypes/html.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (10, 'HTML File', 'text/html', 'html', 100, 'images/attachtypes/html.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (11, 'JPEG Image', 'image/jpeg', 'jpeg', 500, 'images/attachtypes/image.png', 1, '-1', '-1', 1);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (12, 'GZIP Compressed File', 'application/x-gzip', 'gz', 1024, 'images/attachtypes/tar.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (13, 'TAR Compressed File', 'application/x-tar', 'tar', 1024, 'images/attachtypes/tar.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (14, 'CSS Stylesheet', 'text/css', 'css', 100, 'images/attachtypes/css.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (15, 'Adobe Acrobat PDF', 'application/pdf', 'pdf', 2048, 'images/attachtypes/pdf.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (16, 'Bitmap Image', 'image/bmp', 'bmp', 500, 'images/attachtypes/image.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (17, 'Microsoft Word 2007 Document', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'docx', 1024, 'images/attachtypes/doc.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (18, 'Microsoft Excel Document', 'application/vnd.ms-excel', 'xls', 1024, 'images/attachtypes/xls.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (19, 'Microsoft Excel 2007 Document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'xlsx', 1024, 'images/attachtypes/xls.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (20, 'Microsoft PowerPoint Document', 'application/vnd.ms-powerpoint', 'ppt', 1024, 'images/attachtypes/ppt.png', 1, '-1', '-1', 0);";+$inserts[] = "INSERT INTO mybb_attachtypes (atid, name, mimetype, extension, maxsize, icon, enabled, groups, forums, avatarfile) VALUES (21, 'Microsoft PowerPoint 2007 Document', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'pptx', 1024, 'images/attachtypes/ppt.png', 1, '-1', '-1', 0);"; $inserts[] = "INSERT INTO mybb_calendars (name,disporder,startofweek,showbirthdays,eventlimit,moderation,allowhtml,allowmycode,allowimgcode,allowvideocode,allowsmilies) VALUES ('Default Calendar',1,0,1,4,0,0,1,1,1,1);"; @@ -73,6 +73,12 @@ $inserts[] = "INSERT INTO mybb_questions (qid, question, answer, shown, correct, incorrect, active) VALUES(1, 'What does 2 + 2 equal?', '4\nFour', 0, 0, 0, 1);"; +$inserts[] = "INSERT INTO mybb_reportreasons (rid, title, appliesto, extra, disporder) VALUES(1, '<lang:report_reason_other>', 'all', 1, 99);";+$inserts[] = "INSERT INTO mybb_reportreasons (rid, title, appliesto, extra, disporder) VALUES(2, '<lang:report_reason_rules>', 'all', 0, 1);";+$inserts[] = "INSERT INTO mybb_reportreasons (rid, title, appliesto, extra, disporder) VALUES(3, '<lang:report_reason_bad>', 'all', 0, 2);";+$inserts[] = "INSERT INTO mybb_reportreasons (rid, title, appliesto, extra, disporder) VALUES(4, '<lang:report_reason_spam>', 'all', 0, 3);";+$inserts[] = "INSERT INTO mybb_reportreasons (rid, title, appliesto, extra, disporder) VALUES(5, '<lang:report_reason_wrong>', 'post', 0, 4);";+ $inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(1, 'Smile', ':)', 'images/smilies/smile.png', 1, 1);"; $inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(2, 'Wink', ';)', 'images/smilies/wink.png', 2, 1);"; $inserts[] = "INSERT INTO mybb_smilies (sid, name, find, image, disporder, showclickable) VALUES(3, 'Cool', ':cool:', 'images/smilies/cool.png', 3, 1);";@@ -150,6 +156,7 @@ $inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('39','footer','<lang:group_footer>','1');"; $inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('40','video','<lang:group_video>','1');"; $inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('41','sendthread','<lang:group_sendthread>','1');";+$inserts[] = "INSERT INTO mybb_templategroups (gid,prefix,title,isdefault) VALUES ('42','mycode','<lang:group_mycode>','1');"; $inserts[] = "INSERT INTO mybb_usertitles (utid, posts, title, stars, starimage) VALUES (1, 0, 'Newbie', 1, '');"; $inserts[] = "INSERT INTO mybb_usertitles (utid, posts, title, stars, starimage) VALUES (2, 1, 'Junior Member', 2, '');";
Vulnerability Existed: no No CWE - No vulnerability detected Old Code: Multiple INSERT statements with limited column specification Fixed Code: INSERT statements expanded with additional columns (enabled, groups, forums, avatarfile) and new report reason/template group inserts added Explanation: This diff shows schema updates to the MyBB database initialization script. The changes add new columns to the mybb_attachtypes table (enabled, groups, forums, avatarfile) with hardcoded safe default values (1, '-1', '-1', 0/1). The new reportreasons and templategroup inserts use language constants (e.g., '<lang:report_reason_other>') which are safe placeholder syntax for MyBB's language system. All values are literal strings/numbers in a database initialization script, not user-supplied input. There is no SQL injection risk, no command injection, and no other OWASP vulnerabilities. This is a straightforward schema migration that does not introduce or fix security vulnerabilities—it's simply adding new required columns and records during installation.
--- cache/mybb_mybb_1807/install/resources/mysql_db_tables.php 2025-12-06 11:32:55.266131148 +0000+++ cache/mybb_mybb_1808/install/resources/mysql_db_tables.php 2025-12-06 11:32:56.006178935 +0000@@ -102,6 +102,10 @@ extension varchar(10) NOT NULL default '', maxsize int(15) unsigned NOT NULL default '0', icon varchar(100) NOT NULL default '',+ enabled tinyint(1) NOT NULL default '1',+ groups TEXT NOT NULL,+ forums TEXT NOT NULL,+ avatarfile tinyint(1) NOT NULL default '0', PRIMARY KEY (atid) ) ENGINE=MyISAM;"; @@ -660,6 +664,7 @@ id3 int unsigned NOT NULL default '0', uid int unsigned NOT NULL default '0', reportstatus tinyint(1) NOT NULL default '0',+ reasonid smallint unsigned NOT NULL default '0', reason varchar(250) NOT NULL default '', type varchar(50) NOT NULL default '', reports int unsigned NOT NULL default '0',@@ -671,6 +676,15 @@ PRIMARY KEY (rid) ) ENGINE=MyISAM;"; +$tables[] = "CREATE TABLE mybb_reportreasons (+ rid int unsigned NOT NULL auto_increment,+ title varchar(250) NOT NULL default '',+ appliesto varchar(250) NOT NULL default '',+ extra tinyint(1) NOT NULL default '0',+ disporder smallint unsigned NOT NULL default '0',+ PRIMARY KEY (rid)+) ENGINE=MyISAM;";+ $tables[] = "CREATE TABLE mybb_reputation ( rid int unsigned NOT NULL auto_increment, uid int unsigned NOT NULL default '0',
Based on my analysis of the provided diff from a MyBB installation script, here are my findings: --- ## Analysis Results **Vulnerability Existed: no** **SQL Injection - CWE 89 - install/resources/mysql_db_tables.php (All sections)** **Old Code:** ```sql extension varchar(10) NOT NULL default '', maxsize int(15) unsigned NOT NULL default '0', icon varchar(100) NOT NULL default '', PRIMARY KEY (atid) ) ENGINE=MyISAM; ``` **Fixed Code:** ```sql extension varchar(10) NOT NULL default '', maxsize int(15) unsigned NOT NULL default '0', icon varchar(100) NOT NULL default '', enabled tinyint(1) NOT NULL default '1', groups TEXT NOT NULL, forums TEXT NOT NULL, avatarfile tinyint(1) NOT NULL default '0', PRIMARY KEY (atid) ) ENGINE=MyISAM; ``` **Explanation:** This diff adds new database schema columns to the MyBB installation script. The changes are pure SQL CREATE TABLE statements with hardcoded column definitions—there are no user inputs, string interpolations, or dynamic SQL construction. The additions (enabled, groups, forums, avatarfile fields and the new reportreasons table) follow the same safe pattern as existing columns. No SQL injection vulnerability exists here since the SQL is static and defined at installation time. --- **Vulnerability Existed: no** **Data Type Mismatch / Potential Data Loss - CWE 197 - install/resources/mysql_db_tables.php (line 664)** **Old Code:** ```sql reason varchar(250) NOT NULL default '', type varchar(50) NOT NULL default '', ``` **Fixed Code:** ```sql reasonid smallint unsigned NOT NULL default '0', reason varchar(250) NOT NULL default '', type varchar(50) NOT NULL default '', ``` **Explanation:** The addition of a `reasonid` field as a foreign key reference (smallint unsigned) to the new `reportreasons` table is a structural improvement, not a security vulnerability. It normalizes the schema by replacing inline reason text with a reference ID, which is a best practice. The smallint range (0-65535) is reasonable for a reasons lookup table. No vulnerability exists here. --- **Summary:** This diff contains no security vulnerabilities. It represents database schema migrations that add new fields and a new lookup table following existing code patterns and SQL best practices.
--- cache/mybb_mybb_1807/install/resources/pgsql_db_tables.php 2025-12-06 11:32:55.266131148 +0000+++ cache/mybb_mybb_1808/install/resources/pgsql_db_tables.php 2025-12-06 11:32:56.006178935 +0000@@ -103,6 +103,10 @@ extension varchar(10) NOT NULL default '', maxsize int NOT NULL default '0', icon varchar(100) NOT NULL default '',+ enabled smallint NOT NULL default '1',+ groups text NOT NULL default '-1',+ forums text NOT NULL default '-1',+ avatarfile smallint NOT NULL default '0', PRIMARY KEY (atid) );"; @@ -633,6 +637,7 @@ id3 int NOT NULL default '0', uid int NOT NULL default '0', reportstatus smallint NOT NULL default '0',+ reasonid smallint NOT NULL default '0', reason varchar(250) NOT NULL default '', type varchar(50) NOT NULL default '', reports int NOT NULL default '0',@@ -642,6 +647,15 @@ PRIMARY KEY (rid) );"; +$tables[] = "CREATE TABLE mybb_reportreasons (+ rid serial,+ title varchar(250) NOT NULL default '',+ appliesto varchar(250) NOT NULL default '',+ extra smallint NOT NULL default '0',+ disporder smallint NOT NULL default '0',+ PRIMARY KEY (rid)+);";+ $tables[] = "CREATE TABLE mybb_reputation ( rid serial, uid int NOT NULL default '0',
Let me analyze the provided database schema diff for security vulnerabilities. ## Analysis Results **Vulnerability 1:** Vulnerability Existed: no Improper Input Validation in String Field - CWE-20 - install/resources/pgsql_db_tables.php (Line 638) Old Code: ```sql reason varchar(250) NOT NULL default '', ``` Fixed Code: ```sql reason varchar(250) NOT NULL default '', reasonid smallint NOT NULL default '0', ``` Explanation: The diff shows a new field `reasonid` being added to the `mybb_reports` table as a foreign key reference to the new `mybb_reportreasons` table. This is actually a security improvement rather than a vulnerability fix. By introducing a structured `reasonid` field that references a separate table, the schema now enforces referential integrity instead of allowing arbitrary text in the `reason` field. This reduces risk of injection attacks and data inconsistency. **Vulnerability 2:** Vulnerability Existed: no Improper Access Control - CWE-276 - install/resources/pgsql_db_tables.php (Lines 106-109) Old Code: ```sql icon varchar(100) NOT NULL default '', PRIMARY KEY (atid) ``` Fixed Code: ```sql icon varchar(100) NOT NULL default '', enabled smallint NOT NULL default '1', groups text NOT NULL default '-1', forums text NOT NULL default '-1', avatarfile smallint NOT NULL default '0', PRIMARY KEY (atid) ``` Explanation: Four new columns are added to the attachment type table: `enabled`, `groups`, `forums`, and `avatarfile`. These appear to be access control and feature flags. The fields default to permissive values (`enabled=1`, `groups/forums='-1'` to denote "all"). These are schema-level access control mechanisms, which is appropriate design. No vulnerability exists here—these are intended security control fields that allow per-attachment-type permission management. **Vulnerability 3:** Vulnerability Existed: no New Table Creation - CWE-89 (SQL Injection) - install/resources/pgsql_db_tables.php (Lines 644-652) Old Code: ``` [Table does not exist in original version] ``` Fixed Code: ```sql CREATE TABLE mybb_reportreasons ( rid serial, title varchar(250) NOT NULL default '', appliesto varchar(250) NOT NULL default '', extra smallint NOT NULL default '0', disporder smallint NOT NULL default '0', PRIMARY KEY (rid) ); ``` Explanation: A new `mybb_reportreasons` table is created to centralize report reason definitions. The schema is properly structured with appropriate data types and primary keys. No direct SQL injection vulnerabilities are present in the table definition itself. The string fields (`title`, `appliesto`) use `varchar` with reasonable length limits (250 chars), which is appropriate. No vulnerability exists in this schema change. --- **Summary:** This diff represents a database schema migration that adds referential integrity and access control features. No active security vulnerabilities are introduced or fixed in this code—these are schema enhancement changes.
--- cache/mybb_mybb_1807/install/resources/sqlite_db_tables.php 2025-12-06 11:32:55.266131148 +0000+++ cache/mybb_mybb_1808/install/resources/sqlite_db_tables.php 2025-12-06 11:32:56.006178935 +0000@@ -92,7 +92,11 @@ mimetype varchar(120) NOT NULL default '', extension varchar(10) NOT NULL default '', maxsize int(15) NOT NULL default '0',- icon varchar(100) NOT NULL default ''+ icon varchar(100) NOT NULL default '',+ enabled tinyint(1) NOT NULL default '1',+ groups TEXT NOT NULL,+ forums TEXT NOT NULL,+ avatarfile tinyint(1) NOT NULL default '0' );"; $tables[] = "CREATE TABLE mybb_awaitingactivation (@@ -589,6 +593,7 @@ id3 int NOT NULL default '0', uid int NOT NULL default '0', reportstatus tinyint(1) NOT NULL default '0',+ reasonid smallint NOT NULL default '0', reason varchar(250) NOT NULL default '', type varchar(50) NOT NULL default '', reports int NOT NULL default '0',@@ -597,6 +602,14 @@ lastreport int NOT NULL default '0' );"; +$tables[] = "CREATE TABLE mybb_reportreasons (+ rid INTEGER PRIMARY KEY,+ title varchar(250) NOT NULL default '',+ appliesto varchar(250) NOT NULL default '',+ extra tinyint(1) NOT NULL default '0',+ disporder smallint NOT NULL default '0'+);";+ $tables[] = "CREATE TABLE mybb_reputation ( rid INTEGER PRIMARY KEY, uid int NOT NULL default '0',
Vulnerability Existed: no Explanation: This diff contains schema changes to a MyBB forum database installation file. The modifications add new columns to existing tables (`mybb_attachments`, `mybb_reports`) and introduce a new table (`mybb_reportreasons`). **Security Analysis:** 1. **No SQL Injection**: The file is a PHP script defining SQL schema strings as constants/array elements. There is no dynamic SQL construction, user input, or variable interpolation in the diff. The SQL statements are hardcoded schema definitions. 2. **New Columns**: The added columns (`enabled`, `groups`, `forums`, `avatarfile`, `reasonid`) use appropriate data types (tinyint, TEXT, smallint) and include NOT NULL constraints with sensible defaults. No security vulnerabilities introduced. 3. **New Table**: The `mybb_reportreasons` table is a straightforward schema definition with standard column types and constraints. The PRIMARY KEY is properly defined. 4. **No Access Control Issues**: This file defines database schema. Access control is enforced at the application layer, not in the schema definition itself. 5. **No Data Exposure**: The schema additions do not expose sensitive data or create unintended data storage mechanisms. **Conclusion**: These are routine database schema maintenance changes that add features (report reasons system, attachment controls) without introducing security vulnerabilities. The changes appear to be part of a MyBB forum software update adding reporting and permission features.
--- cache/mybb_mybb_1807/install/resources/upgrade12.php 2025-12-06 11:32:55.266131148 +0000+++ cache/mybb_mybb_1808/install/resources/upgrade12.php 2025-12-06 11:32:56.006178935 +0000@@ -1347,7 +1347,7 @@ * * Please see the MyBB Docs for advanced * database configuration for larger installations- * http://docs.mybb.com/+ * https://docs.mybb.com/ */ \$config['database']['type'] = '{$config['dbtype']}';
I'll analyze this code diff for security vulnerabilities. **Vulnerability Existed:** no **No Vulnerabilities Found** **Explanation:** This diff shows a single change: updating a URL in a comment from `http://docs.mybb.com/` to `https://docs.mybb.com/`. This is not a security fix addressing a vulnerability in the code itself, but rather a documentation improvement promoting the use of HTTPS over HTTP. The change: - Affects only a comment (lines starting with `*` in a PHP docblock) - Does not alter any executable code - Does not fix a code vulnerability - Simply updates a reference URL to use the secure HTTPS protocol instead of unencrypted HTTP This is a best practice update for documentation links but does not constitute a fix for any code-level security vulnerability such as injection flaws, insecure deserialization, authentication bypasses, or other OWASP Top 10 issues.
--- cache/mybb_mybb_1807/install/resources/upgrade17.php 2025-12-06 11:32:55.266131148 +0000+++ cache/mybb_mybb_1808/install/resources/upgrade17.php 2025-12-06 11:32:56.006178935 +0000@@ -712,7 +712,7 @@ * * Please see the MyBB Docs for advanced * database configuration for larger installations- * http://docs.mybb.com/+ * https://docs.mybb.com/ */ {$database_config}
Vulnerability Existed: no No CWE - No CWE ID - install/resources/upgrade17.php [715] [Old Code] * http://docs.mybb.com/ [Fixed Code] * https://docs.mybb.com/ Explanation: This change upgrades a documentation URL from HTTP to HTTPS. This is a security improvement rather than a vulnerability fix. The old code referenced an insecure HTTP endpoint for documentation, while the fixed code uses the secure HTTPS protocol. This prevents potential man-in-the-middle attacks and ensures encrypted communication when users access the documentation. No vulnerability existed in the code itself—this is a best practice update to use secure communication protocols.
--- cache/mybb_mybb_1807/install/resources/upgrade2.php 2025-12-06 11:32:55.270131406 +0000+++ cache/mybb_mybb_1808/install/resources/upgrade2.php 2025-12-06 11:32:56.006178935 +0000@@ -182,7 +182,7 @@ $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'bbname', 'Board Name', 'The name of your message boards. We recommend that it is not over 75 characters.', 'text', 'MyBB Forums', 1, 1);"); $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'bburl', 'Board URL', 'The url to your forums.<br />Include the http://. Do NOT include a trailing slash.', 'text', '', 2, 1);"); $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'homename', 'Homepage Name', 'The name of your homepage. This will appear in the footer with a link to it.', 'text', 'MyBB', 3, 1);");- $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'homeurl', 'Homepage URL', 'The full URL of your homepage. This will be linked to in the footer along with its name.', 'text', 'http://www.mybb.com', 4, 1);");+ $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'homeurl', 'Homepage URL', 'The full URL of your homepage. This will be linked to in the footer along with its name.', 'text', 'https://mybb.com', 4, 1);"); $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'dateformat', 'Date Format', 'The format of the dates used on the forum. This format uses the PHP date() function. We recommend not changing this unless you know what you\'re doing.', 'text', 'm-d-Y', 1, 3);"); $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'adminemail', 'Admin Email', 'The administrator\'s email address. This will be used for outgoing emails sent via the forums.', 'text', '', 5, 1);"); $db->write_query("INSERT INTO ".TABLE_PREFIX."settings (sid, name, title, description, optionscode, value, disporder, gid) VALUES (NULL, 'timeformat', 'Time Format', 'The format of the times used on the forum. This format uses PHP\'s date() function. We recommend not changing this unless you know what you\'re doing.', 'text', 'h:i A', 2, 3);");
``` Vulnerability Existed: no No Security Vulnerability Detected Old Code: 'http://www.mybb.com' Fixed Code: 'https://mybb.com' Explanation: This is a configuration update, not a security fix for a vulnerability. The change upgrades the default homepage URL from HTTP to HTTPS (a best practice for secure communication) and updates the domain from www.mybb.com to mybb.com. This is a safe, non-security-related modification to a default configuration value in an installation script. No code is executing user input, no injection vectors are present, and no privilege escalation occurs. This is simply updating a hardcoded default value. ```
--- cache/mybb_mybb_1807/install/resources/upgrade35.php 2025-12-06 11:32:55.282132181 +0000+++ cache/mybb_mybb_1808/install/resources/upgrade35.php 2025-12-06 11:32:56.010179192 +0000@@ -45,7 +45,7 @@ } // Remove "Are You a Human" captcha- $db->update_query('settings', array('value' => 1), "name='captchaimage' AND value=3");+ $db->update_query('settings', array('value' => '1'), "name='captchaimage' AND value='3'"); $db->delete_query('settings', "name IN ('ayahpublisherkey', 'ayahscoringkey')"); $db->delete_query('templates', "title IN ('member_register_regimage_ayah', 'post_captcha_ayah')");
```
Vulnerability Existed: no
Explanation:
This diff shows a change from numeric values (1, 3) to string values ('1', '3') in a database query. While the change itself doesn't introduce a vulnerability, it also doesn't fix one.
The original code uses numeric literals in the WHERE clause: `value=3` and in the UPDATE array: `'value' => 1`. This is safe because:
1. The `update_query()` function is a parameterized query method provided by MyBB's database abstraction layer
2. The values are literal constants, not user input
3. No SQL injection vector exists here - the code is not concatenating user-supplied data into the query
4. Type coercion between numeric and string values in SQL comparisons is handled safely by the database layer
The change to string values ('1', '3') is stylistic but doesn't address or indicate a security vulnerability. It may have been made for consistency or type-safety reasons, but no vulnerable code existed in the original version.
```
--- /dev/null+++ cache/mybb_mybb_1808/install/resources/upgrade36.php@@ -0,0 +1,235 @@+<?php+/**+ * MyBB 1.8+ * Copyright 2014 MyBB Group, All Rights Reserved+ *+ * Website: http://www.mybb.com+ * License: http://www.mybb.com/about/license+ *+ */++/**+ * Upgrade Script: 1.8.7+ */++$upgrade_detail = array(+ "revert_all_templates" => 0,+ "revert_all_themes" => 0,+ "revert_all_settings" => 0+);++@set_time_limit(0);++function upgrade36_dbchanges()+{+ global $db, $output, $mybb;++ $output->print_header("Updating Database");+ echo "<p>Performing necessary upgrade queries...</p>";+ flush();++ if($db->field_exists('enabled', 'attachtypes'))+ {+ $db->drop_column('attachtypes', 'enabled');+ }++ if($db->field_exists('groups', 'attachtypes'))+ {+ $db->drop_column('attachtypes', 'groups');+ }++ if($db->field_exists('forums', 'attachtypes'))+ {+ $db->drop_column('attachtypes', 'forums');+ }++ if($db->field_exists('avatarfile', 'attachtypes'))+ {+ $db->drop_column('attachtypes', 'avatarfile');+ }++ switch($db->type)+ {+ case "pgsql":+ $db->add_column('attachtypes', 'enabled', "smallint NOT NULL default '1'");+ $db->add_column('attachtypes', 'groups', "text NOT NULL default '-1'");+ $db->add_column('attachtypes', 'forums', "text NOT NULL default '-1'");+ $db->add_column('attachtypes', 'avatarfile', "smallint NOT NULL default '0'");+ break;+ default:+ $db->add_column('attachtypes', 'enabled', "tinyint(1) NOT NULL default '1'");+ $db->add_column('attachtypes', 'groups', "TEXT NOT NULL");+ $db->add_column('attachtypes', 'forums', "TEXT NOT NULL");+ $db->add_column('attachtypes', 'avatarfile', "tinyint(1) NOT NULL default '0'");++ $db->update_query('attachtypes', array('groups' => '-1', 'forums' => '-1'));+ break;+ }++ $db->update_query('attachtypes', array('avatarfile' => 1), "atid IN (2, 4, 7, 11)");++ if($mybb->settings['username_method'] == 1 || $mybb->settings['username_method'] == 2)+ {+ $query = $db->simple_select('users', 'email, COUNT(email) AS duplicates', "email!=''", array('group_by' => 'email HAVING duplicates>1'));+ if($db->num_rows($query))+ {+ $db->update_query('settings', array('value' => 0), "name='username_method'");+ }+ else+ {+ $db->update_query('settings', array('value' => 0), "name='allowmultipleemails'");+ }+ }++ $query = $db->simple_select("templategroups", "COUNT(*) as numexists", "prefix='mycode'");+ if($db->fetch_field($query, "numexists") == 0)+ {+ $db->insert_query("templategroups", array('prefix' => 'mycode', 'title' => '<lang:group_mycode>', 'isdefault' => '1'));+ }++ $output->print_contents("<p>Click next to continue with the upgrade process.</p>");+ $output->print_footer("36_dbchanges2");+}++function upgrade36_dbchanges2()+{+ global $output, $db, $cache;++ $output->print_header("Updating Database");+ echo "<p>Performing necessary upgrade queries...</p>";+ flush();++ if($db->field_exists('reasonid', 'reportedcontent'))+ {+ $db->drop_column("reportedcontent", "reasonid");+ }++ switch($db->type)+ {+ case "pgsql":+ case "sqlite":+ $db->add_column("reportedcontent", "reasonid", "smallint NOT NULL default '0' AFTER reportstatus");+ break;+ default:+ $db->add_column("reportedcontent", "reasonid", "smallint unsigned NOT NULL default '0' AFTER reportstatus");+ break;+ }+++ if($db->table_exists("reportreasons"))+ {+ $db->drop_table("reportreasons");+ }++ $collation = $db->build_create_table_collation();++ switch($db->type)+ {+ case "pgsql":+ $db->write_query("CREATE TABLE ".TABLE_PREFIX."reportreasons (+ rid serial,+ title varchar(250) NOT NULL default '',+ appliesto varchar(250) NOT NULL default '',+ extra smallint NOT NULL default '0',+ disporder smallint NOT NULL default '0',+ PRIMARY KEY (rid)+ );");+ break;+ case "sqlite":+ $db->write_query("CREATE TABLE ".TABLE_PREFIX."reportreasons (+ rid INTEGER PRIMARY KEY,+ title varchar(250) NOT NULL default '',+ appliesto varchar(250) NOT NULL default '',+ extra tinyint(1) NOT NULL default '0',+ disporder smallint NOT NULL default '0',+ );");+ break;+ default:+ $db->write_query("CREATE TABLE ".TABLE_PREFIX."reportreasons (+ rid int unsigned NOT NULL auto_increment,+ title varchar(250) NOT NULL default '',+ appliesto varchar(250) NOT NULL default '',+ extra tinyint(1) NOT NULL default '0',+ disporder smallint unsigned NOT NULL default '0',+ PRIMARY KEY (rid)+ ) ENGINE=MyISAM{$collation};");+ break;+ }++ $reportreasons = array(+ array(+ 'rid' => 1,+ 'title' => "<lang:report_reason_other>",+ 'appliesto' => "all",+ 'extra' => 1,+ 'disporder' => 99+ ),+ array(+ 'rid' => 2,+ 'title' => "<lang:report_reason_rules>",+ 'appliesto' => "all",+ 'extra' => 0,+ 'disporder' => 1+ ),+ array(+ 'rid' => 3,+ 'title' => "<lang:report_reason_bad>",+ 'appliesto' => "all",+ 'extra' => 0,+ 'disporder' => 2+ ),+ array(+ 'rid' => 4,+ 'title' => "<lang:report_reason_spam>",+ 'appliesto' => "all",+ 'extra' => 0,+ 'disporder' => 3+ ),+ array(+ 'rid' => 5,+ 'title' => "<lang:report_reason_wrong>",+ 'appliesto' => "post",+ 'extra' => 0,+ 'disporder' => 4+ )+ );++ $db->insert_query_multiple('reportreasons', $reportreasons);++ $templang = new MyLanguage();+ $templang->set_path(MYBB_ROOT."inc/languages");++ $langs = array_keys($templang->get_languages());++ foreach($langs as $langname)+ {+ unset($templang);+ $templang = new MyLanguage();+ $templang->set_path(MYBB_ROOT."inc/languages");+ $templang->set_language($langname);+ $templang->load("report");++ if(!empty($templang->report_reason_rules) && $templang->report_reason_rules != '')+ {+ $db->update_query("reportedcontent", array("reasonid" => 2, "reason" => ''), "reason = '".$db->escape_string("\n".$templang->report_reason_rules)."'");+ }+ if(!empty($templang->report_reason_bad) && $templang->report_reason_bad != '')+ {+ $db->update_query("reportedcontent", array("reasonid" => 3, "reason" => ''), "reason = '".$db->escape_string("\n".$templang->report_reason_bad)."'");+ }+ if(!empty($templang->report_reason_spam) && $templang->report_reason_spam != '')+ {+ $db->update_query("reportedcontent", array("reasonid" => 4, "reason" => ''), "reason = '".$db->escape_string("\n".$templang->report_reason_spam)."'");+ }+ if(!empty($templang->report_reason_wrong) && $templang->report_reason_wrong != '')+ {+ $db->update_query("reportedcontent", array("reasonid" => 5, "reason" => ''), "reason = '".$db->escape_string("\n".$templang->report_reason_wrong)."'");+ }+ }++ // Any reason not converted is treated as "Other" with extra text specified+ $db->update_query("reportedcontent", array('reasonid' => 1), "reason != ''");++ $output->print_contents("<p>Click next to continue with the upgrade process.</p>");+ $output->print_footer("36_done");+}
Vulnerability Existed: yes
TRUE POSITIVE
SQL Injection - CWE-89 - install/resources/upgrade36.php Lines 206-219
[Old Code]
```php
$db->update_query("reportedcontent", array("reasonid" => 2, "reason" => ''), "reason = '".$db->escape_string("\n".$templang->report_reason_rules)."'");
$db->update_query("reportedcontent", array("reasonid" => 3, "reason" => ''), "reason = '".$db->escape_string("\n".$templang->report_reason_bad)."'");
$db->update_query("reportedcontent", array("reasonid" => 4, "reason" => ''), "reason = '".$db->escape_string("\n".$templang->report_reason_spam)."'");
$db->update_query("reportedcontent", array("reasonid" => 5, "reason" => ''), "reason = '".$db->escape_string("\n".$templang->report_reason_wrong)."'");
```
[Fixed Code]
The code shown is the vulnerable code (this is a new file addition, not a fix).
Explanation:
The WHERE clause is constructed by concatenating escaped strings directly into the SQL query string rather than using parameterized queries. While `$db->escape_string()` is called, the vulnerable pattern is evident: `"reason = '".$db->escape_string(...)."'"`. If the database abstraction layer's `update_query()` method doesn't support parameterized WHERE clauses natively, this remains vulnerable to SQL injection. The proper fix would be to pass the WHERE condition through the database layer's parameter binding mechanism rather than string concatenation. The reliance on escape_string() for WHERE clauses is a known anti-pattern that can be bypassed with certain character encodings or database configurations.
--- cache/mybb_mybb_1807/install/upgrade.php 2025-12-06 11:32:55.282132181 +0000+++ cache/mybb_mybb_1808/install/upgrade.php 2025-12-06 11:32:56.010179192 +0000@@ -143,7 +143,7 @@ // Include the necessary contants for installation $grouppermignore = array("gid", "type", "title", "description", "namestyle", "usertitle", "stars", "starimage", "image");-$groupzerogreater = array("pmquota", "maxpmrecipients", "maxreputationsday", "attachquota", "maxemails", "maxwarningsday", "maxposts", "edittimelimit", "canusesigxposts", "maxreputationsperthread");+$groupzerogreater = array("pmquota", "maxpmrecipients", "maxreputationsday", "attachquota", "maxemails", "maxwarningsday", "maxposts", "edittimelimit", "canusesigxposts", "maxreputationsperuser", "maxreputationsperthread", "emailfloodtime"); $displaygroupfields = array("title", "description", "namestyle", "usertitle", "stars", "starimage", "image"); $fpermfields = array('canview', 'canviewthreads', 'candlattachments', 'canpostthreads', 'canpostreplys', 'canpostattachments', 'canratethreads', 'caneditposts', 'candeleteposts', 'candeletethreads', 'caneditattachments', 'canpostpolls', 'canvotepolls', 'cansearch', 'modposts', 'modthreads', 'modattachments', 'mod_edit_posts'); @@ -163,7 +163,7 @@ if($mybb->input['action'] == "logout" && $mybb->user['uid']) { // Check session ID if we have one- if($mybb->get_input('logoutkey') != $mybb->user['logoutkey'])+ if($mybb->get_input('logoutkey') !== $mybb->user['logoutkey']) { $output->print_error("Your user ID could not be verified to log you out. This may have been because a malicious Javascript was attempting to log you out automatically. If you intended to log out, please click the Log Out button at the top menu."); }@@ -480,7 +480,7 @@ } else {- $output->print_error();+ $output->print_error($lang->no_theme_functions_file); } // Import master theme@@ -567,8 +567,7 @@ $output->print_header($lang->upgrade_datacache_building); $contents .= $lang->upgrade_building_datacache;- require_once MYBB_ROOT."inc/class_datacache.php";- $cache = new datacache;+ $cache->update_version(); $cache->update_attachtypes(); $cache->update_smilies();@@ -596,6 +595,7 @@ $cache->update_groupleaders(); $cache->update_threadprefixes(); $cache->update_forumsdisplay();+ $cache->update_reportreasons(true); $contents .= $lang->done."</p>";
Based on my analysis of the provided diff from `install/upgrade.php`, here are the security vulnerabilities identified:
---
**Vulnerability 1:**
Vulnerability Existed: **yes**
**Type Juggling / Loose Comparison - CWE-1025** - CWE-1025 - install/upgrade.php Line 166
**Old Code:**
```php
if($mybb->get_input('logoutkey') != $mybb->user['logoutkey'])
```
**Fixed Code:**
```php
if($mybb->get_input('logoutkey') !== $mybb->user['logoutkey'])
```
**Explanation:**
The old code uses the loose comparison operator `!=` instead of the strict comparison operator `!==`. This is a type juggling vulnerability where PHP's loose comparison rules could allow an attacker to bypass the logout key verification. For example, if `logoutkey` is `0` and `$mybb->user['logoutkey']` is a string that starts with a non-numeric character, the loose comparison would evaluate them as equal. This is a security-critical comparison for logout verification, so type juggling could allow unauthorized logout manipulation. The fix correctly uses `!==` to enforce strict type and value comparison.
---
**Vulnerability 2:**
Vulnerability Existed: **yes**
**Missing Error Message - CWE-391 (Unchecked Error Condition)** - CWE-391 - install/upgrade.php Line 483
**Old Code:**
```php
$output->print_error();
```
**Fixed Code:**
```php
$output->print_error($lang->no_theme_functions_file);
```
**Explanation:**
The old code calls `print_error()` without providing an error message, which results in a generic or undefined error message being displayed to the user. This is poor error handling and could mask important security-related issues. The fix provides a specific error message (`$lang->no_theme_functions_file`), which improves error reporting and helps administrators understand what went wrong. While not a direct vulnerability, this pattern can lead to information disclosure or debugging difficulties.
---
**Vulnerability 3:**
Vulnerability Existed: **not sure**
**Use After Free / Undefined Variable - CWE-416/CWE-457** - CWE-457 - install/upgrade.php Line 572
**Old Code:**
```php
require_once MYBB_ROOT."inc/class_datacache.php";
$cache = new datacache;
$cache->update_version();
```
**Fixed Code:**
```php
$cache->update_version();
```
**Explanation:**
The old code explicitly instantiates a new `datacache` object. The fixed code removes the `require_once` and instantiation, but continues to call methods on `$cache` without any visible initialization in this diff snippet. This suggests that either: (1) `$cache` is initialized elsewhere in the script before this point, or (2) this is introducing an undefined variable bug (CWE-457). Without seeing the full context of where `$cache` is defined, it's uncertain whether this is a legitimate refactor (cache reuse from earlier initialization) or a vulnerability. If `$cache` is not guaranteed to be initialized before line 572, this would cause a fatal error or undefined variable access.
--- cache/mybb_mybb_1807/managegroup.php 2025-12-06 11:32:55.294132956 +0000+++ cache/mybb_mybb_1808/managegroup.php 2025-12-06 11:32:56.022179968 +0000@@ -212,6 +212,7 @@ $user['reason'] = htmlspecialchars_uni($user['reason']); $altbg = alt_trow(); $regdate = my_date($mybb->settings['dateformat'], $user['regdate']);+ $user['username'] = htmlspecialchars_uni($user['username']); $user['profilelink'] = build_profile_link($user['username'], $user['uid']); eval("\$users .= \"".$templates->get("managegroup_joinrequests_request")."\";"); }@@ -309,7 +310,8 @@ $leader_count = $db->num_rows($query); while($leader = $db->fetch_array($query)) {- $leader_name = format_name(htmlspecialchars_uni($leader['username']), $leader['usergroup'], $leader['displaygroup']);+ $leader['username'] = htmlspecialchars_uni($leader['username']);+ $leader_name = format_name($leader['username'], $leader['usergroup'], $leader['displaygroup']); $leader_profile_link = build_profile_link($leader_name, $leader['uid']); $leaders_array[] = $leader['uid'];@@ -392,6 +394,7 @@ $email = ''; } + $user['username'] = htmlspecialchars_uni($user['username']); $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']); $user['profilelink'] = build_profile_link($user['username'], $user['uid']); if(in_array($user['uid'], $leaders_array))
Vulnerability Existed: no [Cross-Site Scripting (XSS)] - [CWE-79] - [managegroup.php] [Lines 215, 313-314, 397-398] Old Code (Line 215): ```php $user['profilelink'] = build_profile_link($user['username'], $user['uid']); ``` Fixed Code (Line 215): ```php $user['username'] = htmlspecialchars_uni($user['username']); $user['profilelink'] = build_profile_link($user['username'], $user['uid']); ``` Explanation: This diff does NOT represent a fix for a vulnerability that existed in the code. Rather, it represents a **security hardening improvement** where the developers are adding output encoding that was previously missing. The old code was vulnerable to XSS because `$user['username']` was used without proper HTML escaping in multiple locations where it was passed to functions like `build_profile_link()` and used in template rendering. The new code adds `htmlspecialchars_uni()` calls to properly escape the username before use, preventing XSS attacks. This is a preventive fix addressing a potential XSS vulnerability that could have been exploited if user-controlled data reached these code paths unescaped. --- Vulnerability Existed: no [Cross-Site Scripting (XSS)] - [CWE-79] - [managegroup.php] [Lines 313-314] Old Code (Line 312): ```php $leader_name = format_name(htmlspecialchars_uni($leader['username']), $leader['usergroup'], $leader['displaygroup']); ``` Fixed Code (Lines 313-314): ```php $leader['username'] = htmlspecialchars_uni($leader['username']); $leader_name = format_name($leader['username'], $leader['usergroup'], $leader['displaygroup']); ``` Explanation: This refactoring extracts the `htmlspecialchars_uni()` call into a separate statement and stores it in `$leader['username']`. While functionally equivalent to the old code, this change improves code consistency across the file by standardizing how usernames are escaped. It allows the escaped username to be reused in subsequent operations (like `build_profile_link()`) without re-escaping, improving efficiency and reducing redundant function calls. --- Vulnerability Existed: no [Cross-Site Scripting (XSS)] - [CWE-79] - [managegroup.php] [Lines 397-398] Old Code (Line 395): ```php $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']); ``` Fixed Code (Lines 397-398): ```php $user['username'] = htmlspecialchars_uni($user['username']); $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']); ``` Explanation: This adds HTML encoding before the `format_name()` call, ensuring the username is properly escaped before being formatted for display. This prevents XSS vulnerabilities where an attacker could inject malicious JavaScript through a crafted username stored in the database.
--- cache/mybb_mybb_1807/member.php 2025-12-06 11:32:55.294132956 +0000+++ cache/mybb_mybb_1808/member.php 2025-12-06 11:32:56.022179968 +0000@@ -14,14 +14,17 @@ define("ALLOWABLE_PAGE", "register,do_register,login,do_login,logout,lostpw,do_lostpw,activate,resendactivation,do_resendactivation,resetpassword,viewnotes"); $nosession['avatar'] = 1; -$templatelist = "member_register,member_register_hiddencaptcha,member_coppa_form,member_register_coppa,member_register_agreement_coppa,member_register_agreement,usercp_options_tppselect,usercp_options_pppselect,member_register_referrer,member_register_customfield,member_register_requiredfields"; -$templatelist .= ",member_resetpassword,member_loggedin_notice,member_profile_away,member_emailuser,member_register_regimage,member_register_regimage_recaptcha,member_register_regimage_nocaptcha,post_captcha_hidden,post_captcha,post_captcha_recaptcha,member_profile_addremove,member_emailuser_guest"; -$templatelist .= ",member_profile_email,member_profile_offline,member_profile_reputation,member_profile_warn,member_profile_warninglevel,member_profile_customfields_field,member_profile_customfields,member_profile_adminoptions,member_profile,member_login,member_profile_online,member_viewnotes"; -$templatelist .= ",member_profile_signature,member_profile_avatar,member_profile_groupimage,member_profile_referrals,member_profile_website,member_profile_reputation_vote,member_activate,member_resendactivation,member_lostpw,member_register_additionalfields,member_register_password,usercp_options_pppselect_option"; -$templatelist .= ",member_profile_modoptions_manageuser,member_profile_modoptions_editprofile,member_profile_modoptions_banuser,member_profile_modoptions_viewnotes,member_profile_modoptions,member_profile_modoptions_editnotes,member_profile_modoptions_purgespammer,postbit_reputation_formatted,postbit_warninglevel_formatted"; -$templatelist .= ",usercp_profile_profilefields_select_option,usercp_profile_profilefields_multiselect,usercp_profile_profilefields_select,usercp_profile_profilefields_textarea,usercp_profile_profilefields_radio,usercp_profile_profilefields_checkbox,usercp_profile_profilefields_text,usercp_options_tppselect_option"; -$templatelist .= ",member_register_question,member_register_question_refresh,usercp_options_timezone,usercp_options_timezone_option,usercp_options_language_option,member_register_language,member_profile_userstar,member_profile_customfields_field_multi_item,member_profile_customfields_field_multi,member_register_day"; -$templatelist .= ",member_profile_contact_fields_aim,member_profile_contact_fields_google,member_profile_contact_fields_icq,member_profile_contact_fields_skype,member_profile_contact_fields_yahoo,member_profile_pm,member_profile_contact_details,member_profile_banned,member_profile_findposts,member_profile_findthreads"; ++$templatelist = "member_register,member_register_hiddencaptcha,member_coppa_form,member_register_coppa,member_register_agreement_coppa,member_register_agreement,member_register_customfield,member_register_requiredfields,member_register_password"; +$templatelist .= ",member_loggedin_notice,member_profile_away,member_register_regimage,member_register_regimage_recaptcha,member_register_regimage_nocaptcha,post_captcha_hidden,post_captcha,post_captcha_recaptcha,member_viewnotes,member_register_referrer"; +$templatelist .= ",member_profile_email,member_profile_offline,member_profile_reputation,member_profile_warn,member_profile_warninglevel,member_profile_customfields_field,member_profile_customfields,member_profile_adminoptions,member_profile"; +$templatelist .= ",member_profile_signature,member_profile_avatar,member_profile_groupimage,member_profile_referrals,member_profile_website,member_profile_reputation_vote,member_activate,member_resendactivation,member_lostpw,member_register_additionalfields"; +$templatelist .= ",member_profile_modoptions_manageuser,member_profile_modoptions_editprofile,member_profile_modoptions_banuser,member_profile_modoptions_viewnotes,member_profile_modoptions_editnotes,member_profile_modoptions_purgespammer"; +$templatelist .= ",usercp_profile_profilefields_select_option,usercp_profile_profilefields_multiselect,usercp_profile_profilefields_select,usercp_profile_profilefields_textarea,usercp_profile_profilefields_radio,usercp_profile_profilefields_checkbox"; +$templatelist .= ",member_register_question,member_register_question_refresh,usercp_options_timezone,usercp_options_timezone_option,usercp_options_language_option,member_register_language,member_profile_customfields_field_multi_item,member_profile_customfields_field_multi"; +$templatelist .= ",member_profile_contact_fields_aim,member_profile_contact_fields_google,member_profile_contact_fields_icq,member_profile_contact_fields_skype,member_profile_contact_fields_yahoo,member_profile_pm,member_profile_contact_details,member_profile_banned"; +$templatelist .= ",member_profile_banned_remaining,member_profile_addremove,member_emailuser_guest,member_register_day,usercp_options_tppselect_option,postbit_warninglevel_formatted,member_profile_userstar,member_profile_findposts,member_profile_findthreads";+$templatelist .= ",usercp_options_tppselect,usercp_options_pppselect,member_resetpassword,member_login,member_profile_online,usercp_options_pppselect_option,postbit_reputation_formatted,member_emailuser,member_profile_modoptions,usercp_profile_profilefields_text"; require_once "./global.php"; require_once MYBB_ROOT."inc/functions_post.php"; @@ -392,7 +395,7 @@ if(isset($mybb->cookies['coppauser'])) { - $lang->redirect_registered_coppa_activate = $lang->sprintf($lang->redirect_registered_coppa_activate, $mybb->settings['bbname'], $user_info['username']); + $lang->redirect_registered_coppa_activate = $lang->sprintf($lang->redirect_registered_coppa_activate, $mybb->settings['bbname'], htmlspecialchars_uni($user_info['username'])); my_unsetcookie("coppauser"); my_unsetcookie("coppadob"); $plugins->run_hooks("member_do_register_end"); @@ -427,7 +430,7 @@ } my_mail($user_info['email'], $emailsubject, $emailmessage); - $lang->redirect_registered_activation = $lang->sprintf($lang->redirect_registered_activation, $mybb->settings['bbname'], $user_info['username']); + $lang->redirect_registered_activation = $lang->sprintf($lang->redirect_registered_activation, $mybb->settings['bbname'], htmlspecialchars_uni($user_info['username'])); $plugins->run_hooks("member_do_register_end"); @@ -519,7 +522,7 @@ } // Load language - if($recipient['language'] != $mybb->user['language'] && $lang->language_exists($recipient['language'])) + if($recipient['language'] != $lang->language && $lang->language_exists($recipient['language'])) { $reset_lang = true; $lang->set_language($recipient['language']); @@ -534,12 +537,12 @@ // Reset language if(isset($reset_lang)) { - $lang->set_language($mybb->user['language']); + $lang->set_language($mybb->settings['bblanguage']); $lang->load("member"); } } - $lang->redirect_registered_admin_activate = $lang->sprintf($lang->redirect_registered_admin_activate, $mybb->settings['bbname'], $user_info['username']); + $lang->redirect_registered_admin_activate = $lang->sprintf($lang->redirect_registered_admin_activate, $mybb->settings['bbname'], htmlspecialchars_uni($user_info['username'])); $plugins->run_hooks("member_do_register_end"); @@ -607,7 +610,7 @@ } // Load language - if($recipient['language'] != $mybb->user['language'] && $lang->language_exists($recipient['language'])) + if($recipient['language'] != $lang->language && $lang->language_exists($recipient['language'])) { $reset_lang = true; $lang->set_language($recipient['language']); @@ -622,7 +625,7 @@ // Reset language if(isset($reset_lang)) { - $lang->set_language($mybb->user['language']); + $lang->set_language($mybb->settings['bblanguage']); $lang->load("member"); } } @@ -653,7 +656,7 @@ } my_mail($user_info['email'], $emailsubject, $emailmessage); - $lang->redirect_registered_activation = $lang->sprintf($lang->redirect_registered_activation, $mybb->settings['bbname'], $user_info['username']); + $lang->redirect_registered_activation = $lang->sprintf($lang->redirect_registered_activation, $mybb->settings['bbname'], htmlspecialchars_uni($user_info['username'])); $plugins->run_hooks("member_do_register_end"); @@ -661,7 +664,7 @@ } else { - $lang->redirect_registered = $lang->sprintf($lang->redirect_registered, $mybb->settings['bbname'], $user_info['username']); + $lang->redirect_registered = $lang->sprintf($lang->redirect_registered, $mybb->settings['bbname'], htmlspecialchars_uni($user_info['username'])); $plugins->run_hooks("member_do_register_end"); @@ -829,12 +832,14 @@ { $query = $db->simple_select("users", "uid,username", "uid='".(int)$mybb->cookies['mybb']['referrer']."'"); $ref = $db->fetch_array($query); + $ref['username'] = htmlspecialchars_uni($ref['username']); $referrername = $ref['username']; } elseif(isset($referrer)) { $query = $db->simple_select("users", "username", "uid='".(int)$referrer['uid']."'"); $ref = $db->fetch_array($query); + $ref['username'] = htmlspecialchars_uni($ref['username']); $referrername = $ref['username']; } elseif(!empty($referrername)) @@ -1390,6 +1395,7 @@ { $user['username'] = ''; } + $user['username'] = htmlspecialchars_uni($user['username']); eval("\$activate = \"".$templates->get("member_activate")."\";"); output_page($activate); @@ -1590,6 +1596,7 @@ { $user = get_user($mybb->get_input('uid', MyBB::INPUT_INT)); } + if(isset($mybb->input['code']) && $user) { $query = $db->simple_select("awaitingactivation", "code", "uid='".$user['uid']."' AND type='p'"); @@ -1607,11 +1614,35 @@ if($password_length < 8) { - $password_length = 8; + $password_length = min(8, (int)$mybb->settings['maxpasswordlength']); } - $password = random_str($password_length); - $logindetails = update_password($user['uid'], md5($password), $user['salt']); + // Set up user handler. + require_once MYBB_ROOT.'inc/datahandlers/user.php'; + $userhandler = new UserDataHandler('update'); + + while(!$userhandler->verify_password()) + { + $password = random_str($password_length, $mybb->settings['requirecomplexpasswords']); + + $userhandler->set_data(array( + 'uid' => $user['uid'], + 'username' => $user['username'], + 'email' => $user['email'], + 'password' => $password + )); + + $userhandler->set_validated(true); + $userhandler->errors = array(); + } + + $userhandler->update_user(); + + $logindetails = array( + 'salt' => $userhandler->data['salt'], + 'password' => $userhandler->data['saltedpw'], + 'loginkey' => $userhandler->data['loginkey'], + ); $email = $user['email']; @@ -1651,6 +1682,7 @@ { $user['username'] = ''; } + $user['username'] = htmlspecialchars_uni($user['username']); eval("\$activate = \"".$templates->get("member_resetpassword")."\";"); output_page($activate); @@ -1738,7 +1770,7 @@ $mybb->input['url'] = str_replace('&', '&', $mybb->input['url']); // Redirect to the URL if it is not member.php - redirect(htmlentities($mybb->input['url']), $lang->redirect_loggedin); + redirect($mybb->input['url'], $lang->redirect_loggedin); } else { @@ -1757,6 +1789,7 @@ $member_loggedin_notice = ""; if($mybb->user['uid'] != 0) { + $mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']); $lang->already_logged_in = $lang->sprintf($lang->already_logged_in, build_profile_link($mybb->user['username'], $mybb->user['uid'])); eval("\$member_loggedin_notice = \"".$templates->get("member_loggedin_notice")."\";"); } @@ -1852,12 +1885,12 @@ } // Check session ID if we have one - if(isset($mybb->input['sid']) && $mybb->get_input('sid') != $session->sid) + if(isset($mybb->input['sid']) && $mybb->get_input('sid') !== $session->sid) { error($lang->error_notloggedout); } // Otherwise, check logoutkey - else if(!isset($mybb->input['sid']) && $mybb->get_input('logoutkey') != $mybb->user['logoutkey']) + else if(!isset($mybb->input['sid']) && $mybb->get_input('logoutkey') !== $mybb->user['logoutkey']) { error($lang->error_notloggedout); } @@ -1894,6 +1927,7 @@ error_no_permission(); } + $user['username'] = htmlspecialchars_uni($user['username']); $lang->view_notes_for = $lang->sprintf($lang->view_notes_for, $user['username']); $user['usernotes'] = nl2br(htmlspecialchars_uni($user['usernotes'])); @@ -1935,6 +1969,8 @@ $uid = $memprofile['uid']; + $me_username = $memprofile['username']; + $memprofile['username'] = htmlspecialchars_uni($memprofile['username']); $lang->profile = $lang->sprintf($lang->profile, $memprofile['username']); // Get member's permissions @@ -1964,7 +2000,7 @@ $website = $sendemail = $sendpm = $contact_details = ''; - if($memprofile['website'] && !is_member($mybb->settings['hidewebsite']) && $memperms['canchangewebsite'] == 1) + if(my_validate_url($memprofile['website']) && !is_member($mybb->settings['hidewebsite']) && $memperms['canchangewebsite'] == 1) { $memprofile['website'] = htmlspecialchars_uni($memprofile['website']); $bgcolor = alt_trow(); @@ -2022,7 +2058,7 @@ "allow_mycode" => $mybb->settings['sigmycode'], "allow_smilies" => $mybb->settings['sigsmilies'], "allow_imgcode" => $mybb->settings['sigimgcode'], - "me_username" => $memprofile['username'], + "me_username" => $me_username, "filter_badwords" => 1 ); @@ -2582,25 +2618,28 @@ $timeremaining = nice_time($remaining, array('short' => 1, 'seconds' => false)).""; + $banned_class = ''; if($remaining < 3600) { - $timeremaining = "<span style=\"color: red;\">({$timeremaining} {$lang->ban_remaining})</span>"; + $banned_class = "high_banned"; } else if($remaining < 86400) { - $timeremaining = "<span style=\"color: maroon;\">({$timeremaining} {$lang->ban_remaining})</span>"; + $banned_class = "moderate_banned"; } else if($remaining < 604800) { - $timeremaining = "<span style=\"color: green;\">({$timeremaining} {$lang->ban_remaining})</span>"; + $banned_class = "low_banned"; } else { - $timeremaining = "({$timeremaining} {$lang->ban_remaining})"; + $banned_class = "normal_banned"; } + + eval('$timeremaining = "'.$templates->get('member_profile_banned_remaining').'";'); } - $memban['adminuser'] = build_profile_link($memban['adminuser'], $memban['admin']); + $memban['adminuser'] = build_profile_link(htmlspecialchars_uni($memban['adminuser']), $memban['admin']); // Display a nice warning to the user eval('$bannedbit = "'.$templates->get('member_profile_banned').'";'); @@ -2957,6 +2996,7 @@ $query = $db->simple_select("users", "uid, username, email, hideemail, ignorelist", "uid='".$mybb->get_input('uid', MyBB::INPUT_INT)."'"); $to_user = $db->fetch_array($query); + $to_user['username'] = htmlspecialchars_uni($to_user['username']); $lang->email_user = $lang->sprintf($lang->email_user, $to_user['username']); if(!$to_user['uid'])
Analyzing the security-related diff for MyBB member.php...
---
**Vulnerability 1:**
Vulnerability Existed: yes
TRUE POSITIVE
**Improper Neutralization of Input During Web Page Generation (Cross-Site Scripting) - CWE-79** - member.php (Lines 398, 433, 542, 659, 667)
Old Code:
```php
$lang->redirect_registered_coppa_activate = $lang->sprintf($lang->redirect_registered_coppa_activate, $mybb->settings['bbname'], $user_info['username']);
```
Fixed Code:
```php
$lang->redirect_registered_coppa_activate = $lang->sprintf($lang->redirect_registered_coppa_activate, $mybb->settings['bbname'], htmlspecialchars_uni($user_info['username']));
```
Explanation:
User-controlled data (`$user_info['username']`) was being passed directly to `sprintf()` without HTML entity encoding, then output in messages that would be displayed to users. An attacker could register with a username containing HTML/JavaScript payloads and have that executed when the message is displayed. The fix applies `htmlspecialchars_uni()` to properly escape the username before output. This same XSS vulnerability existed at multiple locations (lines 398, 433, 542, 659, 667, 835, 843, 1398, 1685, 1792, 1930, 2999) where `$user_info['username']`, `$ref['username']`, `$memprofile['username']`, and `$memban['adminuser']` were output without encoding.
---
**Vulnerability 2:**
Vulnerability Existed: yes
TRUE POSITIVE
**Improper Input Validation - CWE-20** - member.php (Line 1618)
Old Code:
```php
if($password_length < 8)
{
$password_length = 8;
}
$password = random_str($password_length);
$logindetails = update_password($user['uid'], md5($password), $user['salt']);
```
Fixed Code:
```php
if($password_length < 8)
{
$password_length = min(8, (int)$mybb->settings['maxpasswordlength']);
}
// Set up user handler.
require_once MYBB_ROOT.'inc/datahandlers/user.php';
$userhandler = new UserDataHandler('update');
while(!$userhandler->verify_password())
{
$password = random_str($password_length, $mybb->settings['requirecomplexpasswords']);
$userhandler->set_data(array(
'uid' => $user['uid'],
'username' => $user['username'],
'email' => $user['email'],
'password' => $password
));
$userhandler->set_validated(true);
$userhandler->errors = array();
}
$userhandler->update_user();
$logindetails = array(
'salt' => $userhandler->data['salt'],
'password' => $userhandler->data['saltedpw'],
'loginkey' => $userhandler->data['loginkey'],
);
```
Explanation:
The original code generated passwords using raw `random_str()` without respecting password complexity requirements or maximum length constraints. It also directly used `md5()` for password hashing without using the proper user handler validation. The fix properly constrains the password length between 8 and the configured maximum, respects password complexity settings, validates the password through the UserDataHandler's `verify_password()` method, and uses the handler's proper salting/hashing mechanism instead of manual md5.
---
**Vulnerability 3:**
Vulnerability Existed: yes
FALSE POSITIVE
**Open Redirect - CWE-601** - member.php (Line 1773)
Old Code:
```php
redirect(htmlentities($mybb->input['url']), $lang->redirect_loggedin);
```
Fixed Code:
```php
redirect($mybb->input['url'], $lang->redirect_loggedin);
```
Explanation:
This appears counterintuitive (removing HTML encoding), but the vulnerability is that the code was HTML-encoding a URL parameter before passing it to `redirect()`. If the redirect function properly validates URLs to prevent open redirects, the HTML encoding would bypass that validation by converting characters the validator checks for. The fix removes the encoding, allowing the redirect function's proper validation to work. However, if `redirect()` doesn't validate properly, this could introduce an open redirect vulnerability. The real fix should be proper URL validation in `redirect()` itself.
---
**Vulnerability 4:**
Vulnerability Existed: yes
TRUE POSITIVE
**Improper Neutralization of Input During Web Page Generation (Cross-Site Scripting) - CWE-79** - member.php (Lines 2000, 2061)
Old Code:
```php
if($memprofile['website'] && !is_member($mybb->settings['hidewebsite']) && $memperms['canchangewebsite'] == 1)
{
$memprofile['website'] = htmlspecialchars_uni($memprofile['website']);
...
"me_username" => $memprofile['username'],
}
```
Fixed Code:
```php
if(my_validate_url($memprofile['website']) && !is_member($mybb->settings['hidewebsite']) && $memperms['canchangewebsite'] == 1)
{
$memprofile['website'] = htmlspecialchars_uni($memprofile['website']);
...
"me_username" => $me_username,
}
```
Explanation:
The original code checked if `$memprofile['website']` was truthy before using it, but didn't validate that it was actually a valid URL. An attacker could set a website field to `javascript:alert('xss')` which would pass the truthy check. The fix adds proper URL validation via `my_validate_url()` before using the website data. Additionally, the code now uses the pre-escaped `$me_username` variable instead of the raw `$memprofile['username']`, preventing XSS when the username is displayed in a signature context.
---
**Vulnerability 5:**
Vulnerability Existed: yes
FALSE POSITIVE
**Improper Comparison Using Wrong Factors - CWE-597** - member.php (Lines 1855, 1863)
Old Code:
```php
if(isset($mybb->input['sid']) && $mybb->get_input('sid') != $session->sid)
{
error($lang->error_notloggedout);
}
else if(!isset($mybb->input['sid']) && $mybb->get_input('logoutkey') != $mybb->user['logoutkey'])
{
error($lang->error_notloggedout);
}
```
Fixed Code:
```php
if(isset($mybb->input['sid']) && $mybb->get_input('sid') !== $session->sid)
{
error($lang->error_notloggedout);
}
else if(!isset($mybb->input['sid']) && $mybb->get_input('logoutkey') !== $mybb->user['logoutkey'])
{
error($lang->error_notloggedout);
}
```
Explanation:
Using loose comparison (`!=` and `==`) instead of strict comparison (`!==` and `===`) can lead to type juggling vulnerabilities. For example, if `$mybb->get_input('logoutkey')` returns `0` and `$mybb->user['logoutkey']` is an empty string, the loose comparison would consider them equal due to PHP's type juggling, bypassing the logout key validation. The fix uses strict comparison operators to prevent type juggling attacks on security-critical token validation.
--- cache/mybb_mybb_1807/memberlist.php 2025-12-06 11:32:55.294132956 +0000+++ cache/mybb_mybb_1808/memberlist.php 2025-12-06 11:32:56.022179968 +0000@@ -312,7 +312,7 @@ $alt_bg = alt_trow(); - $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']);+ $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); $user['profilelink'] = build_profile_link($user['username'], $user['uid']);
Vulnerability Existed: yes TRUE POSITIVE Cross-Site Scripting (XSS) - CWE-79 - memberlist.php [315] [Old Code] $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']); [Fixed Code] $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); Explanation: The vulnerability existed in the original code. The `$user['username']` variable was passed directly to `format_name()` without any output encoding. If usernames could contain user-controlled input or special characters, this could allow stored XSS attacks where malicious JavaScript or HTML code embedded in a username would be rendered directly in the member list page. The fix applies `htmlspecialchars_uni()` to encode the username before passing it to `format_name()`, preventing the interpretation of HTML/JavaScript entities and mitigating the XSS vulnerability.
--- cache/mybb_mybb_1807/misc.php 2025-12-06 11:32:55.294132956 +0000+++ cache/mybb_mybb_1808/misc.php 2025-12-06 11:32:56.026180225 +0000@@ -12,9 +12,11 @@ define("IGNORE_CLEAN_VARS", "sid"); define('THIS_SCRIPT', 'misc.php'); -$templatelist = "misc_rules_forum,misc_help_helpdoc,misc_whoposted_poster,misc_whoposted,misc_smilies_popup_smilie,misc_smilies_popup,misc_smilies_popup_empty,misc_syndication_feedurl,misc_syndication";-$templatelist .= ",misc_buddypopup,misc_buddypopup_user,misc_buddypopup_user_none,misc_buddypopup_user_online,misc_buddypopup_user_offline,misc_buddypopup_user_sendpm,misc_help_search,misc_syndication_forumlist";-$templatelist .= ",misc_smilies,misc_smilies_smilie,misc_help_section_bit,misc_help_section,misc_help,forumdisplay_password_wrongpass,forumdisplay_password,misc_helpresults,misc_helpresults_bit,misc_helpresults_noresults,multipage,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start";+$templatelist = "misc_rules_forum,misc_help_helpdoc,misc_whoposted_poster,misc_whoposted,misc_smilies_popup_smilie,misc_smilies_popup,misc_smilies_popup_empty,misc_smilies_popup_row";+$templatelist .= ",misc_buddypopup,misc_buddypopup_user,misc_buddypopup_user_none,misc_buddypopup_user_online,misc_buddypopup_user_offline,misc_buddypopup_user_sendpm,misc_syndication_forumlist";+$templatelist .= ",misc_smilies,misc_smilies_smilie,misc_help_section_bit,misc_help_section,misc_help,forumdisplay_password_wrongpass,forumdisplay_password,misc_helpresults,misc_helpresults_bit";+$templatelist .= ",multipage,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start";+$templatelist .= ",misc_smilies_popup_no_smilies,misc_smilies_no_smilies,misc_syndication,misc_help_search,misc_helpresults_noresults,misc_syndication_forumlist_forum,misc_syndication_feedurl"; require_once "./global.php"; require_once MYBB_ROOT."inc/functions_post.php";@@ -550,6 +552,7 @@ while($buddy = $db->fetch_array($query)) {+ $buddy['username'] = htmlspecialchars_uni($buddy['username']); $buddy_name = format_name($buddy['username'], $buddy['usergroup'], $buddy['displaygroup']); $profile_link = build_profile_link($buddy_name, $buddy['uid'], '_blank', 'if(window.opener) { window.opener.location = this.href; return false; }'); @@ -692,6 +695,8 @@ { $poster['username'] = $poster['postusername']; }+ $poster['username'] = htmlspecialchars_uni($poster['username']);+ $poster['postusername'] = htmlspecialchars_uni($poster['postusername']); $poster_name = format_name($poster['username'], $poster['usergroup'], $poster['displaygroup']); if($poster['uid']) {@@ -715,9 +720,10 @@ { // make small popup list of smilies $editor = preg_replace('#([^a-zA-Z0-9_-]+)#', '', $mybb->get_input('editor')); $e = 1;- $class = "trow1";- $smilies = "<tr>";+ $smile_icons = '';+ $class = alt_trow(1); $smilies_cache = $cache->read("smilies");+ if(is_array($smilies_cache)) { $extra_class = ' smilie_pointer';@@ -736,10 +742,11 @@ $onclick = " onclick=\"MyBBEditor.insertText(' $smilie_insert ');\""; eval('$smilie_image = "'.$templates->get('smilie', 1, 0).'";');- eval("\$smilies .= \"".$templates->get("misc_smilies_popup_smilie")."\";");+ eval("\$smile_icons .= \"".$templates->get("misc_smilies_popup_smilie")."\";"); if($e == 2) {- $smilies .= "</tr><tr>";+ eval("\$smilies .= \"".$templates->get("misc_smilies_popup_row")."\";");+ $smile_icons = ''; $e = 1; $class = alt_trow(); }@@ -749,10 +756,17 @@ } } }+ if($e == 2) { eval("\$smilies .= \"".$templates->get("misc_smilies_popup_empty")."\";"); }++ if(!$smilies)+ {+ eval("\$smilies = \"".$templates->get("misc_smilies_popup_no_smilies")."\";");+ }+ eval("\$smiliespage = \"".$templates->get("misc_smilies_popup", 1, 0)."\";"); output_page($smiliespage); }@@ -761,6 +775,7 @@ add_breadcrumb($lang->nav_smilies); $class = "trow1"; $smilies_cache = $cache->read("smilies");+ if(is_array($smilies_cache)) { $extra_class = $onclick = '';@@ -776,6 +791,12 @@ $class = alt_trow(); } }++ if(!$smilies)+ {+ eval("\$smilies = \"".$templates->get("misc_smilies_no_smilies")."\";");+ }+ eval("\$smiliespage = \"".$templates->get("misc_smilies")."\";"); output_page($smiliespage); }@@ -833,6 +854,8 @@ $user['yahoo'] = htmlspecialchars_uni($user['yahoo']); $user['aim'] = htmlspecialchars_uni($user['aim']); + $user['username'] = htmlspecialchars_uni($user['username']);+ $lang->chat_on_skype = $lang->sprintf($lang->chat_on_skype, $user['username']); $lang->call_on_skype = $lang->sprintf($lang->call_on_skype, $user['username']); $lang->send_y_message = $lang->sprintf($lang->send_y_message, $user['username']);@@ -1016,7 +1039,7 @@ if($forum['password'] == '' && !in_array($forum['fid'], $unexp) || $forum['password'] && isset($mybb->cookies['forumpass'][$forum['fid']]) && $mybb->cookies['forumpass'][$forum['fid']] === md5($mybb->user['uid'].$forum['password'])) {- $forumlistbits .= "<option value=\"{$forum['fid']}\" $optionselected>$depth {$forum['name']}</option>\n";+ eval("\$forumlistbits .= \"".$templates->get("misc_syndication_forumlist_forum")."\";"); } if(!empty($forumcache[$forum['fid']]))
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - misc.php line 555
[Old Code]
$buddy_name = format_name($buddy['username'], $buddy['usergroup'], $buddy['displaygroup']);
[Fixed Code]
$buddy['username'] = htmlspecialchars_uni($buddy['username']);
$buddy_name = format_name($buddy['username'], $buddy['usergroup'], $buddy['displaygroup']);
Explanation:
The `$buddy['username']` variable from the database was directly passed to `format_name()` without sanitization. If an attacker could inject malicious JavaScript into the username field (or it was compromised in the database), it would be rendered unsanitized in the HTML output, allowing XSS attacks. The fix applies `htmlspecialchars_uni()` to escape special characters before use.
---
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - misc.php lines 698-699
[Old Code]
$poster['username'] = $poster['postusername'];
}
$poster_name = format_name($poster['username'], $poster['usergroup'], $poster['displaygroup']);
[Fixed Code]
$poster['username'] = $poster['postusername'];
}
$poster['username'] = htmlspecialchars_uni($poster['username']);
$poster['postusername'] = htmlspecialchars_uni($poster['postusername']);
$poster_name = format_name($poster['username'], $poster['usergroup'], $poster['displaygroup']);
Explanation:
Similar to the buddy username vulnerability, `$poster['username']` and `$poster['postusername']` could contain unescaped user input from the database. These are passed to `format_name()` without sanitization, creating an XSS vulnerability. The fix applies `htmlspecialchars_uni()` to both variables to escape HTML special characters.
---
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - misc.php line 857
[Old Code]
$user['aim'] = htmlspecialchars_uni($user['aim']);
$lang->chat_on_skype = $lang->sprintf($lang->chat_on_skype, $user['username']);
[Fixed Code]
$user['aim'] = htmlspecialchars_uni($user['aim']);
$user['username'] = htmlspecialchars_uni($user['username']);
$lang->chat_on_skype = $lang->sprintf($lang->chat_on_skype, $user['username']);
Explanation:
The `$user['username']` variable was being used in `sprintf()` calls with language strings without HTML escaping. If the username contains special characters or malicious content, it could be rendered as unescaped HTML/JavaScript in the output. The fix applies `htmlspecialchars_uni()` to sanitize the username before use.
---
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - misc.php line 1042
[Old Code]
$forumlistbits .= "<option value=\"{$forum['fid']}\" $optionselected>$depth {$forum['name']}</option>\n";
[Fixed Code]
eval("\$forumlistbits .= \"".$templates->get("misc_syndication_forumlist_forum")."\";");
Explanation:
The forum name `{$forum['name']}` was directly embedded in HTML without escaping. If a forum name contained HTML/JavaScript characters, it would be rendered unsanitized in the dropdown option, creating an XSS vulnerability. The fix moves the HTML generation to a template system (via `templates->get()`) which should apply proper escaping. This is a structural improvement that helps prevent similar vulnerabilities.
--- cache/mybb_mybb_1807/modcp.php 2025-12-06 11:32:55.298133214 +0000+++ cache/mybb_mybb_1808/modcp.php 2025-12-06 11:32:56.026180225 +0000@@ -11,21 +11,22 @@ define("IN_MYBB", 1); define('THIS_SCRIPT', 'modcp.php'); -$templatelist = "modcp_reports,modcp_reports_report,modcp_reports_multipage,modcp_reports_allreport,modcp_reports_allreports,modcp_modlogs_multipage,modcp_announcements_delete,modcp_announcements_edit,modcp_awaitingmoderation,modcp_banuser_bangroups_hidden";-$templatelist .= ",modcp_reports_allnoreports,modcp_reports_noreports,modcp_banning,modcp_banning_ban,modcp_announcements_announcement_global,modcp_no_announcements_forum,modcp_modqueue_threads_thread,modcp_awaitingthreads,modcp_banuser_bangroups";-$templatelist .= ",modcp_banning_nobanned,modcp_modqueue_threads_empty,modcp_modqueue_masscontrols,modcp_modqueue_threads,modcp_modqueue_posts_post,modcp_modqueue_posts_empty,modcp_awaitingposts,modcp_nav_editprofile";+$templatelist = "modcp_reports,modcp_reports_report,modcp_reports_multipage,modcp_reports_allreport,modcp_reports_allreports,modcp_modlogs_multipage,modcp_announcements_delete,modcp_announcements_edit,modcp_awaitingmoderation";+$templatelist .= ",modcp_reports_allnoreports,modcp_reports_noreports,modcp_banning,modcp_banning_ban,modcp_announcements_announcement_global,modcp_no_announcements_forum,modcp_modqueue_threads_thread,modcp_awaitingthreads,preview";+$templatelist .= ",modcp_banning_nobanned,modcp_modqueue_threads_empty,modcp_modqueue_masscontrols,modcp_modqueue_threads,modcp_modqueue_posts_post,modcp_modqueue_posts_empty,modcp_awaitingposts,modcp_nav_editprofile,modcp_nav_banning"; $templatelist .= ",modcp_nav,modcp_modlogs_noresults,modcp_modlogs_nologs,modcp,modcp_modqueue_posts,modcp_modqueue_attachments_attachment,modcp_modqueue_attachments_empty,modcp_modqueue_attachments,modcp_editprofile_suspensions_info"; $templatelist .= ",modcp_no_announcements_global,modcp_announcements_global,modcp_announcements_forum,modcp_announcements,modcp_editprofile_select_option,modcp_editprofile_select,modcp_finduser_noresults, modcp_nav_forums_posts";-$templatelist .= ",codebuttons,smilieinsert,modcp_announcements_new,modcp_modqueue_empty,forumjump_bit,forumjump_special,modcp_warninglogs_warning_revoked,modcp_warninglogs_warning,modcp_ipsearch_result,modcp_nav_modqueue,modcp_banuser_liftlist";+$templatelist .= ",codebuttons,modcp_announcements_new,modcp_modqueue_empty,forumjump_bit,forumjump_special,modcp_warninglogs_warning_revoked,modcp_warninglogs_warning,modcp_ipsearch_result,modcp_nav_modqueue,modcp_banuser_liftlist"; $templatelist .= ",modcp_modlogs,modcp_finduser_user,modcp_finduser,usercp_profile_customfield,usercp_profile_profilefields,modcp_ipsearch_noresults,modcp_ipsearch_results,modcp_ipsearch_misc_info,modcp_nav_announcements,modcp_modqueue_post_link"; $templatelist .= ",modcp_editprofile,modcp_ipsearch,modcp_banuser_addusername,modcp_banuser,modcp_warninglogs_nologs,modcp_banuser_editusername,modcp_lastattachment,modcp_lastpost,modcp_lastthread,modcp_nobanned,modcp_modqueue_thread_link";-$templatelist .= ",modcp_warninglogs,modcp_modlogs_result,modcp_editprofile_signature,forumjump_advanced,smilieinsert_getmore,smilieinsert_smilie,smilieinsert_smilie_empty,modcp_announcements_forum_nomod,modcp_announcements_announcement";-$templatelist .= ",multipage,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start,modcp_editprofile_away,modcp_awaitingattachments,modcp_modqueue_attachment_link,modcp_latestfivemodactions,modcp_nav_banning";-$templatelist .= ",postbit_groupimage,postbit_userstar,postbit_online,postbit_offline,postbit_away,postbit_avatar,postbit_find,postbit_pm,postbit_email,postbit_www,postbit_author_user,announcement_edit,announcement_quickdelete,postbit,preview,postmodcp_nav_announcements,modcp_nav_reportcenter,modcp_nav_modlogs";-$templatelist .= ",modcp_awaitingmoderation_none,modcp_banning_edit,modcp_banuser_bangroups_group,modcp_banuser_lift,modcp_modlogs_result_announcement,modcp_modlogs_result_forum,modcp_modlogs_result_post,modcp_modlogs_result_thread,modcp_modlogs_user";+$templatelist .= ",modcp_warninglogs,modcp_modlogs_result,modcp_editprofile_signature,forumjump_advanced,modcp_announcements_forum_nomod,modcp_announcements_announcement,usercp_profile_away,modcp_modlogs_user,modcp_editprofile_away";+$templatelist .= ",multipage,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start,modcp_awaitingattachments,modcp_modqueue_attachment_link";+$templatelist .= ",postbit_groupimage,postbit_userstar,postbit_online,postbit_offline,postbit_away,postbit_avatar,postbit_find,postbit_pm,postbit_email,postbit_www,postbit_author_user,announcement_edit,announcement_quickdelete";+$templatelist .= ",modcp_awaitingmoderation_none,modcp_banning_edit,modcp_banuser_bangroups_group,modcp_banuser_lift,modcp_modlogs_result_announcement,modcp_modlogs_result_forum,modcp_modlogs_result_post,modcp_modlogs_result_thread"; $templatelist .= ",modcp_nav_warninglogs,modcp_nav_ipsearch,modcp_nav_users,modcp_announcements_day,modcp_announcements_month_start,modcp_announcements_month_end,modcp_announcements_announcement_expired,modcp_announcements_announcement_active";-$templatelist .= ",modcp_modqueue_link_forum,modcp_modqueue_link_thread,usercp_profile_day,usercp_profile_away,modcp_ipsearch_result_regip,modcp_ipsearch_result_lastip,modcp_ipsearch_result_post,modcp_ipsearch_results_information,usercp_profile_profilefields_text";-$templatelist .= ",usercp_profile_profilefields_select_option,usercp_profile_profilefields_multiselect,usercp_profile_profilefields_select,usercp_profile_profilefields_textarea,usercp_profile_profilefields_radio,usercp_profile_profilefields_checkbox";+$templatelist .= ",modcp_modqueue_link_forum,modcp_modqueue_link_thread,usercp_profile_day,modcp_ipsearch_result_regip,modcp_ipsearch_result_lastip,modcp_ipsearch_result_post,modcp_ipsearch_results_information,usercp_profile_profilefields_text";+$templatelist .= ",usercp_profile_profilefields_select_option,usercp_profile_profilefields_multiselect,usercp_profile_profilefields_select,usercp_profile_profilefields_textarea,usercp_profile_profilefields_radio,postbit";+$templatelist .= ",modcp_banning_remaining,postmodcp_nav_announcements,modcp_nav_reportcenter,modcp_nav_modlogs,modcp_latestfivemodactions,modcp_banuser_bangroups_hidden,modcp_banuser_bangroups,usercp_profile_profilefields_checkbox"; require_once "./global.php"; require_once MYBB_ROOT."inc/functions_user.php";@@ -383,9 +384,10 @@ // Reports $reports = ''; $query = $db->query("- SELECT r.*, u.username+ SELECT r.*, u.username, rr.title FROM ".TABLE_PREFIX."reportedcontent r LEFT JOIN ".TABLE_PREFIX."users u ON (r.uid = u.uid)+ LEFT JOIN ".TABLE_PREFIX."reportreasons rr ON (r.reasonid = rr.rid) WHERE r.reportstatus = '0'{$tflist_reports} ORDER BY r.reports DESC LIMIT {$start}, {$perpage}@@ -509,39 +511,46 @@ { case 'post': $post = get_post_link($report['id'])."#pid{$report['id']}";- $user = build_profile_link($postcache[$report['id']]['username'], $postcache[$report['id']]['uid']);+ $user = build_profile_link(htmlspecialchars_uni($postcache[$report['id']]['username']), $postcache[$report['id']]['uid']); $report_data['content'] = $lang->sprintf($lang->report_info_post, $post, $user); $thread_link = get_thread_link($postcache[$report['id']]['tid']);- $thread_subject = htmlspecialchars_uni($postcache[$report['id']]['subject']);+ $thread_subject = htmlspecialchars_uni($parser->parse_badwords($postcache[$report['id']]['subject'])); $report_data['content'] .= $lang->sprintf($lang->report_info_post_thread, $thread_link, $thread_subject); break; case 'profile':- $user = build_profile_link($usercache[$report['id']]['username'], $usercache[$report['id']]['uid']);+ $user = build_profile_link(htmlspecialchars_uni($usercache[$report['id']]['username']), $usercache[$report['id']]['uid']); $report_data['content'] = $lang->sprintf($lang->report_info_profile, $user); break; case 'reputation': $reputation_link = "reputation.php?uid={$usercache[$report['id3']]['uid']}#rid{$report['id']}";- $bad_user = build_profile_link($usercache[$report['id2']]['username'], $usercache[$report['id2']]['uid']);+ $bad_user = build_profile_link(htmlspecialchars_uni($usercache[$report['id2']]['username']), $usercache[$report['id2']]['uid']); $report_data['content'] = $lang->sprintf($lang->report_info_reputation, $reputation_link, $bad_user); - $good_user = build_profile_link($usercache[$report['id3']]['username'], $usercache[$report['id3']]['uid']);+ $good_user = build_profile_link(htmlspecialchars_uni($usercache[$report['id3']]['username']), $usercache[$report['id3']]['uid']); $report_data['content'] .= $lang->sprintf($lang->report_info_rep_profile, $good_user); break; } // Report reason and comment- $report_data['comment'] = $lang->na;- $report_string = "report_reason_{$report['reason']}";-- if(isset($lang->$report_string))+ if($report['reasonid'] > 0) {- $report_data['comment'] = $lang->$report_string;+ $reason = htmlspecialchars_uni($lang->parse($report['title']));++ if(empty($report['reason']))+ {+ eval("\$report_data['comment'] = \"".$templates->get("modcp_reports_report_comment")."\";");+ }+ else+ {+ $comment = htmlspecialchars_uni($report['reason']);+ eval("\$report_data['comment'] = \"".$templates->get("modcp_reports_report_comment_extra")."\";");+ } }- else if(!empty($report['reason']))+ else {- $report_data['comment'] = htmlspecialchars_uni($report['reason']);+ $report_data['comment'] = $lang->na; } $report_reports = 1;@@ -554,7 +563,7 @@ { if(is_array($usercache[$report['lastreporter']])) {- $lastreport_user = build_profile_link($usercache[$report['lastreporter']]['username'], $report['lastreporter']);+ $lastreport_user = build_profile_link(htmlspecialchars_uni($usercache[$report['lastreporter']]['username']), $report['lastreporter']); } elseif($usercache[$report['lastreporter']] > 0) {@@ -669,7 +678,7 @@ $plugins->run_hooks("modcp_allreports_start"); $query = $db->query("- SELECT r.*, u.username, p.username AS postusername, up.uid AS postuid, t.subject AS threadsubject, prrep.username AS repusername, pr.username AS profileusername+ SELECT r.*, u.username, p.username AS postusername, up.uid AS postuid, t.subject AS threadsubject, prrep.username AS repusername, pr.username AS profileusername, rr.title FROM ".TABLE_PREFIX."reportedcontent r LEFT JOIN ".TABLE_PREFIX."posts p ON (r.id=p.pid) LEFT JOIN ".TABLE_PREFIX."threads t ON (p.tid=t.tid)@@ -677,6 +686,7 @@ LEFT JOIN ".TABLE_PREFIX."users up ON (p.uid=up.uid) LEFT JOIN ".TABLE_PREFIX."users pr ON (pr.uid=r.id) LEFT JOIN ".TABLE_PREFIX."users prrep ON (prrep.uid=r.id2)+ LEFT JOIN ".TABLE_PREFIX."reportreasons rr ON (r.reasonid = rr.rid) {$wflist_reports} ORDER BY r.dateline DESC LIMIT {$start}, {$perpage}@@ -696,28 +706,44 @@ if($report['type'] == 'post') { $post = get_post_link($report['id'])."#pid{$report['id']}";- $user = build_profile_link($report['postusername'], $report['postuid']);+ $user = build_profile_link(htmlspecialchars_uni($report['postusername']), $report['postuid']); $report_data['content'] = $lang->sprintf($lang->report_info_post, $post, $user); $thread_link = get_thread_link($report['id2']);- $thread_subject = htmlspecialchars_uni($report['threadsubject']);+ $thread_subject = htmlspecialchars_uni($parser->parse_badwords($report['threadsubject'])); $report_data['content'] .= $lang->sprintf($lang->report_info_post_thread, $thread_link, $thread_subject); } else if($report['type'] == 'profile') {- $user = build_profile_link($report['profileusername'], $report['id']);+ $user = build_profile_link(htmlspecialchars_uni($report['profileusername']), $report['id']); $report_data['content'] = $lang->sprintf($lang->report_info_profile, $user); } else if($report['type'] == 'reputation') {- $user = build_profile_link($report['repusername'], $report['id2']);+ $user = build_profile_link(htmlspecialchars_uni($report['repusername']), $report['id2']); $reputation_link = "reputation.php?uid={$report['id3']}#rid{$report['id']}"; $report_data['content'] = $lang->sprintf($lang->report_info_reputation, $reputation_link, $user); } // Report reason and comment- $report_data['comment'] = $lang->na;- $report_string = "report_reason_{$report['reason']}";+ if($report['reasonid'] > 0)+ {+ $reason = htmlspecialchars_uni($lang->parse($report['title']));++ if(empty($report['reason']))+ {+ eval("\$report_data['comment'] = \"".$templates->get("modcp_reports_report_comment")."\";");+ }+ else+ {+ $comment = htmlspecialchars_uni($report['reason']);+ eval("\$report_data['comment'] = \"".$templates->get("modcp_reports_report_comment_extra")."\";");+ }+ }+ else+ {+ $report_data['comment'] = $lang->na;+ } $report['reporterlink'] = get_profile_link($report['uid']); if(!$report['username'])@@ -725,15 +751,7 @@ $report['username'] = $lang->na_deleted; $report['reporterlink'] = $post; }-- if(isset($lang->$report_string))- {- $report_data['comment'] = $lang->$report_string;- }- else if(!empty($report['reason']))- {- $report_data['comment'] = htmlspecialchars_uni($report['reason']);- }+ $report['username'] = htmlspecialchars_uni($report['username']); $report_data['reports'] = my_number_format($report['reports']); $report_data['time'] = my_date('relative', $report['dateline']);@@ -889,13 +907,14 @@ $logitem['action'] = htmlspecialchars_uni($logitem['action']); $log_date = my_date('relative', $logitem['dateline']); $trow = alt_trow();+ $logitem['username'] = htmlspecialchars_uni($logitem['username']); $username = format_name($logitem['username'], $logitem['usergroup'], $logitem['displaygroup']); $logitem['profilelink'] = build_profile_link($username, $logitem['uid']); $logitem['ipaddress'] = my_inet_ntop($db->unescape_binary($logitem['ipaddress'])); if($logitem['tsubject']) {- $logitem['tsubject'] = htmlspecialchars_uni($logitem['tsubject']);+ $logitem['tsubject'] = htmlspecialchars_uni($parser->parse_badwords($logitem['tsubject'])); $logitem['thread'] = get_thread_link($logitem['tid']); eval("\$information .= \"".$templates->get("modcp_modlogs_result_thread")."\";"); }@@ -906,7 +925,7 @@ } if($logitem['psubject']) {- $logitem['psubject'] = htmlspecialchars_uni($logitem['psubject']);+ $logitem['psubject'] = htmlspecialchars_uni($parser->parse_badwords($logitem['psubject'])); $logitem['post'] = get_post_link($logitem['pid']); eval("\$information .= \"".$templates->get("modcp_modlogs_result_post")."\";"); }@@ -917,11 +936,12 @@ $data = my_unserialize($logitem['data']); if(!empty($data['uid'])) {+ $data['username'] = htmlspecialchars_uni($data['username']); $information = $lang->sprintf($lang->edited_user_info, htmlspecialchars_uni($data['username']), get_profile_link($data['uid'])); } if(!empty($data['aid'])) {- $data['subject'] = htmlspecialchars_uni($data['subject']);+ $data['subject'] = htmlspecialchars_uni($parser->parse_badwords($data['subject'])); $data['announcement'] = get_announcement_link($data['aid']); eval("\$information .= \"".$templates->get("modcp_modlogs_result_announcement")."\";"); }@@ -1015,7 +1035,7 @@ $query = $db->simple_select("announcements", "aid, subject, fid", "aid='{$aid}'"); $announcement = $db->fetch_array($query);- $announcement['subject'] = htmlspecialchars_uni($announcement['subject']);+ $announcement['subject'] = htmlspecialchars_uni($parser->parse_badwords($announcement['subject'])); if(!$announcement) {@@ -1099,7 +1119,9 @@ $mybb->input['starttime_month'] = '01'; } - $startdate = gmmktime((int)$startdate[0], (int)$startdate[1], 0, $mybb->get_input('starttime_month', MyBB::INPUT_INT), $mybb->get_input('starttime_day', MyBB::INPUT_INT), $mybb->get_input('starttime_year', MyBB::INPUT_INT));+ $localized_time_offset = $mybb->user['timezone']*3600 + $mybb->user['dst']*3600;++ $startdate = gmmktime((int)$startdate[0], (int)$startdate[1], 0, $mybb->get_input('starttime_month', MyBB::INPUT_INT), $mybb->get_input('starttime_day', MyBB::INPUT_INT), $mybb->get_input('starttime_year', MyBB::INPUT_INT)) -$localized_time_offset; if(!checkdate($mybb->get_input('starttime_month', MyBB::INPUT_INT), $mybb->get_input('starttime_day', MyBB::INPUT_INT), $mybb->get_input('starttime_year', MyBB::INPUT_INT)) || $startdate < 0 || $startdate == false) { $errors[] = $lang->error_invalid_start_date;@@ -1117,7 +1139,7 @@ { $mybb->input['endtime_month'] = '01'; }- $enddate = gmmktime((int)$enddate[0], (int)$enddate[1], 0, $mybb->get_input('endtime_month', MyBB::INPUT_INT), $mybb->get_input('endtime_day', MyBB::INPUT_INT), $mybb->get_input('endtime_year', MyBB::INPUT_INT));+ $enddate = gmmktime((int)$enddate[0], (int)$enddate[1], 0, $mybb->get_input('endtime_month', MyBB::INPUT_INT), $mybb->get_input('endtime_day', MyBB::INPUT_INT), $mybb->get_input('endtime_year', MyBB::INPUT_INT)) - $localized_time_offset; if(!checkdate($mybb->get_input('endtime_month', MyBB::INPUT_INT), $mybb->get_input('endtime_day', MyBB::INPUT_INT), $mybb->get_input('endtime_year', MyBB::INPUT_INT)) || $enddate < 0 || $enddate == false) { $errors[] = $lang->error_invalid_end_date;@@ -1239,12 +1261,13 @@ } else {- // Note: dates are in GMT timezone- $starttime_time = gmdate("g:i a", TIME_NOW);- $endtime_time = gmdate("g:i a", TIME_NOW);- $startday = $endday = gmdate("j", TIME_NOW);- $startmonth = $endmonth = gmdate("m", TIME_NOW);- $startdateyear = gmdate("Y", TIME_NOW);+ $localized_time = TIME_NOW + $mybb->user['timezone']*3600 + $mybb->user['dst']*3600;++ $starttime_time = gmdate($mybb->settings['timeformat'], $localized_time);+ $endtime_time = gmdate($mybb->settings['timeformat'], $localized_time);+ $startday = $endday = gmdate("j", TIME_NOW + $localized_time);+ $startmonth = $endmonth = gmdate("m", $localized_time);+ $startdateyear = gmdate("Y", $localized_time); $announcement = array( 'subject' => '',@@ -1469,7 +1492,9 @@ $mybb->input['starttime_month'] = '01'; } - $startdate = gmmktime((int)$startdate[0], (int)$startdate[1], 0, $mybb->get_input('starttime_month', MyBB::INPUT_INT), $mybb->get_input('starttime_day', MyBB::INPUT_INT), $mybb->get_input('starttime_year', MyBB::INPUT_INT));+ $localized_time_offset = TIME_NOW + $mybb->user['timezone']*3600 + $mybb->user['dst']*3600;++ $startdate = gmmktime((int)$startdate[0], (int)$startdate[1], 0, $mybb->get_input('starttime_month', MyBB::INPUT_INT), $mybb->get_input('starttime_day', MyBB::INPUT_INT), $mybb->get_input('starttime_year', MyBB::INPUT_INT)) - $localized_time_offset; if(!checkdate($mybb->get_input('starttime_month', MyBB::INPUT_INT), $mybb->get_input('starttime_day', MyBB::INPUT_INT), $mybb->get_input('starttime_year', MyBB::INPUT_INT)) || $startdate < 0 || $startdate == false) { $errors[] = $lang->error_invalid_start_date;@@ -1487,7 +1512,7 @@ { $mybb->input['endtime_month'] = '01'; }- $enddate = gmmktime((int)$enddate[0], (int)$enddate[1], 0, $mybb->get_input('endtime_month', MyBB::INPUT_INT), $mybb->get_input('endtime_day', MyBB::INPUT_INT), $mybb->get_input('endtime_year', MyBB::INPUT_INT));+ $enddate = gmmktime((int)$enddate[0], (int)$enddate[1], 0, $mybb->get_input('endtime_month', MyBB::INPUT_INT), $mybb->get_input('endtime_day', MyBB::INPUT_INT), $mybb->get_input('endtime_year', MyBB::INPUT_INT)) - $localized_time_offset; if(!checkdate($mybb->get_input('endtime_month', MyBB::INPUT_INT), $mybb->get_input('endtime_day', MyBB::INPUT_INT), $mybb->get_input('endtime_year', MyBB::INPUT_INT)) || $enddate < 0 || $enddate == false) { $errors[] = $lang->error_invalid_end_date;@@ -1641,18 +1666,20 @@ } else {- // Note: dates are in GMT timezone- $starttime_time = gmdate('g:i a', $announcement['startdate']);- $endtime_time = gmdate('g:i a', $announcement['enddate']);+ $localized_time_startdate = $announcement['startdate'] + $mybb->user['timezone']*3600 + $mybb->user['dst']*3600;+ $localized_time_enddate = $announcement['enddate'] + $mybb->user['timezone']*3600 + $mybb->user['dst']*3600;++ $starttime_time = gmdate($mybb->settings['timeformat'], $localized_time_startdate);+ $endtime_time = gmdate($mybb->settings['timeformat'], $localized_time_enddate); - $startday = gmdate('j', $announcement['startdate']);- $endday = gmdate('j', $announcement['enddate']);+ $startday = gmdate('j', $localized_time_startdate);+ $endday = gmdate('j', $localized_time_enddate); - $startmonth = gmdate('m', $announcement['startdate']);- $endmonth = gmdate('m', $announcement['enddate']);+ $startmonth = gmdate('m', $localized_time_startdate);+ $endmonth = gmdate('m', $localized_time_enddate); - $startdateyear = gmdate('Y', $announcement['startdate']);- $enddateyear = gmdate('Y', $announcement['enddate']);+ $startdateyear = gmdate('Y', $localized_time_startdate);+ $enddateyear = gmdate('Y', $localized_time_enddate); $errored = false; }@@ -1841,7 +1868,7 @@ eval("\$icon = \"".$templates->get("modcp_announcements_announcement_active")."\";"); } - $subject = htmlspecialchars_uni($announcement['subject']);+ $subject = htmlspecialchars_uni($parser->parse_badwords($announcement['subject'])); eval("\$announcements_global .= \"".$templates->get("modcp_announcements_announcement_global")."\";"); }@@ -2098,6 +2125,7 @@ { if($thread['threadusername'] != "") {+ $thread['threadusername'] = htmlspecialchars_uni($thread['threadusername']); $profile_link = $thread['threadusername']; } else@@ -2107,6 +2135,7 @@ } else {+ $thread['username'] = htmlspecialchars_uni($thread['username']); $profile_link = build_profile_link($thread['username'], $thread['uid']); } @@ -2219,6 +2248,7 @@ { if($post['postusername'] != "") {+ $post['postusername'] = htmlspecialchars_uni($post['postusername']); $profile_link = $post['postusername']; } else@@ -2228,6 +2258,7 @@ } else {+ $post['username'] = htmlspecialchars_uni($post['username']); $profile_link = build_profile_link($post['username'], $post['uid']); } @@ -2341,13 +2372,14 @@ $attachdate = my_date('relative', $attachment['dateuploaded']); - $attachment['postsubject'] = htmlspecialchars_uni($attachment['postsubject']);+ $attachment['postsubject'] = htmlspecialchars_uni($parser->parse_badwords($attachment['postsubject'])); $attachment['filename'] = htmlspecialchars_uni($attachment['filename']);- $attachment['threadsubject'] = htmlspecialchars_uni($attachment['threadsubject']);+ $attachment['threadsubject'] = htmlspecialchars_uni($parser->parse_badwords($attachment['threadsubject'])); $attachment['filesize'] = get_friendly_size($attachment['filesize']); $link = get_post_link($attachment['pid'], $attachment['tid']) . "#pid{$attachment['pid']}"; $thread_link = get_thread_link($attachment['tid']);+ $attachment['username'] = htmlspecialchars_uni($attachment['username']); $profile_link = build_profile_link($attachment['username'], $attachment['uid']); eval("\$attachments .= \"".$templates->get("modcp_modqueue_attachments_attachment")."\";");@@ -2669,9 +2701,9 @@ error_no_permission(); } - if($user['website'] == "" || $user['website'] == "http://")+ if(!my_validate_url($user['website'])) {- $user['website'] = "http://";+ $user['website'] = ''; } if($user['icq'] != "0")@@ -3015,6 +3047,7 @@ eval("\$customfields = \"".$templates->get("usercp_profile_profilefields")."\";"); } + $user['username'] = htmlspecialchars_uni($user['username']); $lang->edit_profile = $lang->sprintf($lang->edit_profile, $user['username']); $profile_link = build_profile_link(format_name($user['username'], $user['usergroup'], $user['displaygroup']), $user['uid']); @@ -3279,6 +3312,7 @@ while($user = $db->fetch_array($query)) { $alt_row = alt_trow();+ $user['username'] = htmlspecialchars_uni($user['username']); $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']); $user['postnum'] = my_number_format($user['postnum']); $regdate = my_date('relative', $user['regdate']);@@ -3485,8 +3519,10 @@ while($row = $db->fetch_array($query)) { $trow = alt_trow();+ $row['username'] = htmlspecialchars_uni($row['username']); $username = format_name($row['username'], $row['usergroup'], $row['displaygroup']); $username_link = build_profile_link($username, $row['uid']);+ $row['mod_username'] = htmlspecialchars_uni($row['mod_username']); $mod_username = format_name($row['mod_username'], $row['mod_usergroup'], $row['mod_displaygroup']); $mod_username_link = build_profile_link($mod_username, $row['mod_uid']); $issued_date = my_date($mybb->settings['dateformat'], $row['dateline']).' '.my_date($mybb->settings['timeformat'], $row['dateline']);@@ -3730,10 +3766,11 @@ { $query = $db->simple_select('users', 'username, uid, regip, lastip', $user_ip_sql, array('order_by' => 'regdate', 'order_dir' => 'DESC', 'limit_start' => $start, 'limit' => $perpage));- + while($ipaddress = $db->fetch_array($query)) { $result = false;+ $ipaddress['username'] = htmlspecialchars_uni($ipaddress['username']); $profile_link = build_profile_link($ipaddress['username'], $ipaddress['uid']); $trow = alt_trow(); $ip = false;@@ -3818,7 +3855,11 @@ foreach($ipaddresses as $ipaddress) { $ip = my_inet_ntop($db->unescape_binary($ipaddress['ipaddress']));- if(!$ipaddress['username']) $ipaddress['username'] = $ipaddress['postusername']; // Guest username support+ if(!$ipaddress['username'])+ {+ $ipaddress['username'] = $ipaddress['postusername']; // Guest username support+ }+ $ipaddress['username'] = htmlspecialchars_uni($ipaddress['username']); $trow = alt_trow(); if(!$ipaddress['subject']) {@@ -3826,7 +3867,7 @@ } $ipaddress['postlink'] = get_post_link($ipaddress['pid'], $ipaddress['tid']);- $ipaddress['subject'] = htmlspecialchars_uni($ipaddress['subject']);+ $ipaddress['subject'] = htmlspecialchars_uni($parser->parse_badwords($ipaddress['subject'])); $ipaddress['profilelink'] = build_profile_link($ipaddress['username'], $ipaddress['uid']); eval("\$subject = \"".$templates->get("modcp_ipsearch_result_post")."\";");@@ -3992,6 +4033,7 @@ $bannedusers = ''; while($banned = $db->fetch_array($query)) {+ $banned['username'] = htmlspecialchars_uni($banned['username']); $profile_link = build_profile_link($banned['username'], $banned['uid']); // Only show the edit & lift links if current user created ban, or is super mod/admin@@ -4001,7 +4043,7 @@ eval("\$edit_link = \"".$templates->get("modcp_banning_edit")."\";"); } - $admin_profile = build_profile_link($banned['adminuser'], $banned['admin']);+ $admin_profile = build_profile_link(htmlspecialchars_uni($banned['adminuser']), $banned['admin']); $trow = alt_trow(); @@ -4026,22 +4068,32 @@ $timeremaining = nice_time($remaining, array('short' => 1, 'seconds' => false)).""; + $banned_class = '';+ $ban_remaining = "{$timeremaining} {$lang->ban_remaining}";++ if($remaining <= 0)+ {+ $banned_class = "imminent_banned";+ $ban_remaining = $lang->ban_ending_imminently;+ } if($remaining < 3600) {- $timeremaining = "<span style=\"color: red;\">({$timeremaining} {$lang->ban_remaining})</span>";+ $banned_class = "high_banned"; } else if($remaining < 86400) {- $timeremaining = "<span style=\"color: maroon;\">({$timeremaining} {$lang->ban_remaining})</span>";+ $banned_class = "moderate_banned"; } else if($remaining < 604800) {- $timeremaining = "<span style=\"color: green;\">({$timeremaining} {$lang->ban_remaining})</span>";+ $banned_class = "low_banned"; } else {- $timeremaining = "({$timeremaining} {$lang->ban_remaining})";+ $banned_class = "normal_banned"; }++ eval('$timeremaining = "'.$templates->get('modcp_banning_remaining').'";'); } eval("\$bannedusers .= \"".$templates->get("modcp_banning_ban")."\";");@@ -4293,11 +4345,11 @@ $mybb->input['uid'] = $mybb->get_input('uid', MyBB::INPUT_INT); if($mybb->input['uid']) {- add_breadcrumb($lang->mcp_nav_ban_user);+ add_breadcrumb($lang->mcp_nav_editing_ban); } else {- add_breadcrumb($lang->mcp_nav_editing_ban);+ add_breadcrumb($lang->mcp_nav_ban_user); } $plugins->run_hooks("modcp_banuser_start");@@ -4317,7 +4369,7 @@ $banned = $db->fetch_array($query); if($banned['username']) {- $username = htmlspecialchars_uni($banned['username']);+ $username = $banned['username'] = htmlspecialchars_uni($banned['username']); $banreason = htmlspecialchars_uni($banned['reason']); $uid = $mybb->input['uid']; $user = get_user($banned['uid']);@@ -4338,6 +4390,7 @@ if($mybb->input['uid']) { $user = get_user($mybb->input['uid']);+ $user['username'] = htmlspecialchars_uni($user['username']); $username = $user['username']; } else@@ -4378,7 +4431,7 @@ $dateline = $banned['dateline']; } - $thatime = my_date("D, jS M Y @ g:ia", ban_date2timestamp($time, $dateline));+ $thatime = my_date("D, jS M Y @ {$mybb->settings['timeformat']}", ban_date2timestamp($time, $dateline)); $thattime = " ({$thatime})"; } @@ -4493,6 +4546,7 @@ "); $attachment = $db->fetch_array($query); $attachment['date'] = my_date('relative', $attachment['dateuploaded']);+ $attachment['username'] = htmlspecialchars_uni($attachment['username']); $attachment['profilelink'] = build_profile_link($attachment['username'], $attachment['uid']); $attachment['link'] = get_post_link($attachment['pid'], $attachment['tid']); $attachment['filename'] = htmlspecialchars_uni($attachment['filename']);@@ -4530,6 +4584,7 @@ "); $post = $db->fetch_array($query); $post['date'] = my_date('relative', $post['dateline']);+ $post['username'] = htmlspecialchars_uni($post['username']); $post['profilelink'] = build_profile_link($post['username'], $post['uid']); $post['link'] = get_post_link($post['pid'], $post['tid']); $post['subject'] = $post['fullsubject'] = $parser->parse_badwords($post['subject']);@@ -4561,6 +4616,7 @@ $query = $db->simple_select("threads", "tid, subject, uid, username, dateline", "visible='0' {$flist_queue_threads}", array('order_by' => 'dateline', 'order_dir' => 'DESC', 'limit' => 1)); $thread = $db->fetch_array($query); $thread['date'] = my_date('relative', $thread['dateline']);+ $thread['username'] = htmlspecialchars_uni($thread['username']); $thread['profilelink'] = build_profile_link($thread['username'], $thread['uid']); $thread['link'] = get_thread_link($thread['tid']); $thread['subject'] = $thread['fullsubject'] = $parser->parse_badwords($thread['subject']);@@ -4616,13 +4672,14 @@ $logitem['action'] = htmlspecialchars_uni($logitem['action']); $log_date = my_date('relative', $logitem['dateline']); $trow = alt_trow();+ $logitem['username'] = htmlspecialchars_uni($logitem['username']); $username = format_name($logitem['username'], $logitem['usergroup'], $logitem['displaygroup']); $logitem['profilelink'] = build_profile_link($username, $logitem['uid']); $logitem['ipaddress'] = my_inet_ntop($db->unescape_binary($logitem['ipaddress'])); if($logitem['tsubject']) {- $logitem['tsubject'] = htmlspecialchars_uni($logitem['tsubject']);+ $logitem['tsubject'] = htmlspecialchars_uni($parser->parse_badwords($logitem['tsubject'])); $logitem['thread'] = get_thread_link($logitem['tid']); eval("\$information .= \"".$templates->get("modcp_modlogs_result_thread")."\";"); }@@ -4633,7 +4690,7 @@ } if($logitem['psubject']) {- $logitem['psubject'] = htmlspecialchars_uni($logitem['psubject']);+ $logitem['psubject'] = htmlspecialchars_uni($parser->parse_badwords($logitem['psubject'])); $logitem['post'] = get_post_link($logitem['pid']); eval("\$information .= \"".$templates->get("modcp_modlogs_result_post")."\";"); }@@ -4648,7 +4705,7 @@ } if($data['aid']) {- $data['subject'] = htmlspecialchars_uni($data['subject']);+ $data['subject'] = htmlspecialchars_uni($parser->parse_badwords($data['subject'])); $data['announcement'] = get_announcement_link($data['aid']); eval("\$information .= \"".$templates->get("modcp_modlogs_result_announcement")."\";"); }@@ -4688,6 +4745,7 @@ $bannedusers = ''; foreach($banned_cache as $banned) {+ $banned['username'] = htmlspecialchars_uni($banned['username']); $profile_link = build_profile_link($banned['username'], $banned['uid']); // Only show the edit & lift links if current user created ban, or is super mod/admin@@ -4697,7 +4755,7 @@ eval("\$edit_link = \"".$templates->get("modcp_banning_edit")."\";"); } - $admin_profile = build_profile_link($banned['adminuser'], $banned['admin']);+ $admin_profile = build_profile_link(htmlspecialchars_uni($banned['adminuser']), $banned['admin']); $trow = alt_trow(); @@ -4722,26 +4780,32 @@ $timeremaining = nice_time($remaining, array('short' => 1, 'seconds' => false)).""; + $banned_class = '';+ $ban_remaining = "{$timeremaining} {$lang->ban_remaining}";+ if($remaining <= 0) {- $timeremaining = "<span style=\"color: red;\">({$lang->ban_ending_imminently})</span>";+ $banned_class = "imminent_banned";+ $ban_remaining = $lang->ban_ending_imminently; } else if($remaining < 3600) {- $timeremaining = "<span style=\"color: red;\">({$timeremaining} {$lang->ban_remaining})</span>";+ $banned_class = "high_banned"; } else if($remaining < 86400) {- $timeremaining = "<span style=\"color: maroon;\">({$timeremaining} {$lang->ban_remaining})</span>";+ $banned_class = "moderate_banned"; } else if($remaining < 604800) {- $timeremaining = "<span style=\"color: green;\">({$timeremaining} {$lang->ban_remaining})</span>";+ $banned_class = "low_banned"; } else {- $timeremaining = "({$timeremaining} {$lang->ban_remaining})";+ $banned_class = "normal_banned"; }++ eval('$timeremaining = "'.$templates->get('modcp_banning_remaining').'";'); } eval("\$bannedusers .= \"".$templates->get("modcp_banning_ban")."\";");
# Security Analysis: MyBB modcp.php v1807 → v1808
## Vulnerability 1: Code Injection via eval()
**Vulnerability Existed:** yes
**Code Injection - CWE-95** - CWE-95 - modcp.php lines 543, 548, 1027, 4094
**Old Code:**
```php
if(isset($lang->$report_string))
{
$report_data['comment'] = $lang->$report_string;
}
```
**Fixed Code:**
```php
if($report['reasonid'] > 0)
{
$reason = htmlspecialchars_uni($lang->parse($report['title']));
if(empty($report['reason']))
{
eval("\$report_data['comment'] = \"".$templates->get("modcp_reports_report_comment")."\";");
}
else
{
$comment = htmlspecialchars_uni($report['reason']);
eval("\$report_data['comment'] = \"".$templates->get("modcp_reports_report_comment_extra")."\";");
}
}
```
**Explanation:**
The fix introduces **new eval() calls**, which is a severe vulnerability (CWE-95). While the old code used dynamic property access (`$lang->$report_string`), the new code uses `eval()` to interpolate template variables. If `$templates->get()` returns user-controlled data or if the template content contains malicious code, arbitrary PHP code execution is possible. The fix attempts to add escaping via `htmlspecialchars_uni()` and `$lang->parse()`, but `eval()` is inherently dangerous and these escaping functions may not prevent injection if template data is compromised. This is a **regression in security**.
---
## Vulnerability 2: Cross-Site Scripting (XSS) - Incomplete HTML Encoding
**Vulnerability Existed:** not sure
**Improper Neutralization of Input During Web Page Generation - CWE-79** - CWE-79 - modcp.php multiple lines
**Old Code:**
```php
$user = build_profile_link($postcache[$report['id']]['username'], $postcache[$report['id']]['uid']);
```
**Fixed Code:**
```php
$user = build_profile_link(htmlspecialchars_uni($postcache[$report['id']]['username']), $postcache[$report['id']]['uid']);
```
**Explanation:**
The fix adds `htmlspecialchars_uni()` encoding to usernames before passing to `build_profile_link()`. However, this is only effective if `build_profile_link()` doesn't perform additional HTML processing that could double-encode or if the function properly handles pre-encoded input. The uncertainty arises because the security depends on how `build_profile_link()` internally constructs the profile link. If it uses the username in an `href` attribute or similar context, the escaping may not be sufficient for all contexts. The fix is a **positive security improvement** if `build_profile_link()` preserves the encoding correctly.
---
## Vulnerability 3: Server-Side Template Injection via eval()
**Vulnerability Existed:** not sure
**Server-Side Template Injection - CWE-1336** - CWE-1336 - modcp.php lines 543-548, 1027-1034, 4094-4099
**Old Code:**
```php
$report_string = "report_reason_{$report['reason']}";
if(isset($lang->$report_string))
{
$report_data['comment'] = $lang->$report_string;
}
```
**Fixed Code:**
```php
if($report['reasonid'] > 0)
{
$reason = htmlspecialchars_uni($lang->parse($report['title']));
if(empty($report['reason']))
{
eval("\$report_data['comment'] = \"".$templates->get("modcp_reports_report_comment")."\";");
}
else
{
$comment = htmlspecialchars_uni($report['reason']);
eval("\$report_data['comment'] = \"".$templates->get("modcp_reports_report_comment_extra")."\";");
}
}
```
**Explanation:**
While the fix uses `htmlspecialchars_uni()` on the reason and comment data, the use of `eval()` with template content from `$templates->get()` introduces template injection risk. If the template strings contain unescaped variable interpolation (e.g., `{$variable}`), an attacker could manipulate `$report['title']` or `$report['reason']` to inject code. The escaping on these fields may prevent direct code execution, but the eval() of template content itself is risky. The uncertainty is whether `$templates->get()` can be influenced by attackers indirectly through template uploads or if the template parsing is secure.
---
## Summary
The diff contains **security regressions** by introducing `eval()` calls (CWE-95) for template rendering, while also adding positive improvements via `htmlspecialchars_uni()` encoding for XSS prevention. The net security impact is **negative** due to the code injection risks from eval().
--- cache/mybb_mybb_1807/moderation.php 2025-12-06 11:32:55.298133214 +0000+++ cache/mybb_mybb_1808/moderation.php 2025-12-06 11:32:56.026180225 +0000@@ -11,11 +11,14 @@ define("IN_MYBB", 1); define('THIS_SCRIPT', 'moderation.php'); -$templatelist = 'changeuserbox,loginbox,moderation_delayedmoderation_custommodtool,moderation_delayedmodaction_notes,moderation_delayedmoderation_merge,moderation_delayedmoderation_move';-$templatelist .= ',moderation_delayedmoderation,moderation_deletethread,moderation_deletepoll,moderation_mergeposts_post,moderation_viewthreadnotes,moderation_confirmation';-$templatelist .= ',moderation_move,moderation_threadnotes_modaction,moderation_threadnotes_delayedmodaction,moderation_threadnotes,moderation_getip_modoptions,moderation_getip,moderation_getpmip,moderation_merge';-$templatelist .= ',moderation_split_post,moderation_split,moderation_inline_deletethreads,moderation_inline_movethreads,moderation_inline_deleteposts,moderation_inline_mergeposts,moderation_threadnotes_modaction_error';-$templatelist .= ',moderation_inline_splitposts,forumjump_bit,forumjump_special,forumjump_advanced,forumdisplay_password_wrongpass,forumdisplay_password,moderation_inline_moveposts,moderation_delayedmodaction_error,moderation_purgespammer,moderation_delayedmoderation_date_day,moderation_delayedmoderation_date_month';+$templatelist = "changeuserbox,loginbox,moderation_delayedmoderation_custommodtool,moderation_delayedmodaction_notes,moderation_delayedmoderation_merge,moderation_delayedmoderation_move";+$templatelist .= ",moderation_delayedmoderation,moderation_deletethread,moderation_deletepoll,moderation_mergeposts_post,moderation_viewthreadnotes,moderation_confirmation,moderation_purgespammer";+$templatelist .= ",moderation_move,moderation_threadnotes_modaction,moderation_threadnotes_delayedmodaction,moderation_threadnotes,moderation_getip_modoptions,moderation_getip,moderation_getpmip";+$templatelist .= ",moderation_split_post,moderation_inline_deletethreads,moderation_inline_movethreads,moderation_inline_deleteposts,moderation_inline_mergeposts,moderation_threadnotes_modaction_error";+$templatelist .= ",moderation_inline_splitposts,forumjump_special,forumjump_advanced,forumdisplay_password_wrongpass,forumdisplay_password,moderation_inline_moveposts,moderation_delayedmodaction_error";+$templatelist .= ",moderation_delayedmodaction_notes_thread_single,moderation_delayedmodaction_notes_thread_multiple,moderation_delayedmodaction_notes_forum,moderation_delayedmodaction_notes_new_forum";+$templatelist .= ",moderation_delayedmodaction_notes_redirect,moderation_delayedmodaction_notes_merge,moderation_delayedmoderation_thread,moderation_threadnotes_modaction_thread,forumjump_bit";+$templatelist .= ",moderation_delayedmoderation_date_day,moderation_delayedmoderation_date_month,moderation_threadnotes_modaction_post,moderation_merge,moderation_split,moderation_threadnotes_modaction_forum"; require_once "./global.php"; require_once MYBB_ROOT."inc/functions_post.php";@@ -105,6 +108,7 @@ check_forum_password($forum['fid']); } +$mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']); eval("\$loginbox = \"".$templates->get("changeuserbox")."\";"); $allowable_moderation_actions = array("getip", "getpmip", "cancel_delayedmoderation", "delayedmoderation", "threadnotes", "purgespammer", "viewthreadnotes");@@ -145,14 +149,16 @@ case "delayedmoderation": // Verify incoming POST request verify_post_check($mybb->get_input('my_post_key'));+ + $localized_time_offset = $mybb->user['timezone']*3600 + $mybb->user['dst']*3600; if(!$mybb->get_input('date_day', MyBB::INPUT_INT)) {- $mybb->input['date_day'] = date('d', TIME_NOW);+ $mybb->input['date_day'] = gmdate('d', TIME_NOW + $localized_time_offset); } if(!$mybb->get_input('date_month', MyBB::INPUT_INT)) {- $mybb->input['date_month'] = date('m', TIME_NOW);+ $mybb->input['date_month'] = gmdate('m', TIME_NOW + $localized_time_offset); } // Assume in-line moderation if TID is not set@@ -252,7 +258,7 @@ $errors[] = $lang->error_delayedmoderation_invalid_date_month; } - if($mybb->input['date_year'] < gmdate('Y', TIME_NOW))+ if($mybb->input['date_year'] < gmdate('Y', TIME_NOW + $localized_time_offset)) { $errors[] = $lang->error_delayedmoderation_invalid_date_year; }@@ -269,7 +275,7 @@ } } - $rundate = mktime((int)$date_time[0], (int)$date_time[1], date('s', TIME_NOW), $mybb->get_input('date_month', MyBB::INPUT_INT), $mybb->get_input('date_day', MyBB::INPUT_INT), $mybb->get_input('date_year', MyBB::INPUT_INT));+ $rundate = gmmktime((int)$date_time[0], (int)$date_time[1], date('s', TIME_NOW), $mybb->get_input('date_month', MyBB::INPUT_INT), $mybb->get_input('date_day', MyBB::INPUT_INT), $mybb->get_input('date_year', MyBB::INPUT_INT)) - $localized_time_offset; if(!$errors) {@@ -461,31 +467,40 @@ "); } }+ while($delayedmod = $db->fetch_array($query)) {- $delayedmod['dateline'] = my_date("jS M Y, G:i", $delayedmod['delaydateline']);+ $delayedmod['dateline'] = my_date("jS M Y, {$mybb->settings['timeformat']}", $delayedmod['delaydateline']);+ $delayedmod['username'] = htmlspecialchars_uni($delayedmod['username']); $delayedmod['profilelink'] = build_profile_link($delayedmod['username'], $delayedmod['uid']); $delayedmod['action'] = $actions[$delayedmod['type']]; $info = ''; if(strpos($delayedmod['tids'], ',') === false) { $delayed_thread = get_thread($delayedmod['tids']);- $info .= "<strong>{$lang->thread}</strong> <a href=\"".get_thread_link($delayedmod['tids'])."\">".htmlspecialchars_uni($delayed_thread['subject'])."</a><br />";+ $delayed_thread['link'] = get_thread_link($delayed_thread['tid']);+ $delayed_thread['subject'] = htmlspecialchars_uni($parser->parse_badwords($delayed_thread['subject']));+ eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_thread_single")."\";"); } else {- $info .= "<strong>{$lang->thread}</strong> {$lang->multiple_threads}<br />";+ eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_thread_multiple")."\";"); } if($delayedmod['fname']) {- $info .= "<strong>{$lang->forum}</strong> <a href=\"".get_forum_link($delayedmod['fid'])."\">".htmlspecialchars_uni($delayedmod['fname'])."</a><br />";+ $delayedmod['link'] = get_forum_link($delayedmod['fid']);+ $delayedmod['fname'] = htmlspecialchars_uni($delayedmod['fname']);+ eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_forum")."\";"); } $delayedmod['inputs'] = my_unserialize($delayedmod['inputs']); if($delayedmod['type'] == 'move') {- $info .= "<strong>{$lang->new_forum}</strong> <a href=\"".get_forum_link($delayedmod['inputs']['new_forum'])."\">".htmlspecialchars_uni($forum_cache[$delayedmod['inputs']['new_forum']]['name'])."</a><br />";+ $delayedmod['link'] = get_forum_link($delayedmod['inputs']['new_forum']);+ $delayedmod['name'] = htmlspecialchars_uni($forum_cache[$delayedmod['inputs']['new_forum']]['name']);+ eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_new_forum")."\";");+ if($delayedmod['inputs']['method'] == "redirect") { if((int)$delayedmod['inputs']['redirect_expire'] == 0)@@ -496,13 +511,15 @@ { $redirect_expire_bit = (int)$delayedmod['inputs']['redirect_expire']." {$lang->days}"; }- $info .= "<strong>{$lang->leave_redirect_for}</strong> {$redirect_expire_bit}<br />";++ eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_redirect")."\";"); } } else if($delayedmod['type'] == 'merge') {- $info .= "<strong>{$lang->new_subject}</strong> ".htmlspecialchars_uni($delayedmod['inputs']['subject'])."<br />";- $info .= "<strong>{$lang->thread_to_merge_with}</strong> <a href=\"".htmlspecialchars_uni($delayedmod['inputs']['threadurl'])."\">".htmlspecialchars_uni($delayedmod['inputs']['threadurl'])."</a><br />";+ $delayedmod['subject'] = htmlspecialchars_uni($delayedmod['inputs']['subject']);+ $delayedmod['threadurl'] = htmlspecialchars_uni($delayedmod['inputs']['threadurl']);+ eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_merge")."\";"); } eval("\$delayedmods .= \"".$templates->get("moderation_delayedmodaction_notes")."\";");@@ -518,7 +535,8 @@ if($mybb->get_input('tid', MyBB::INPUT_INT)) { $lang->threads = $lang->thread;- $threads = "<a href=\"".get_thread_link($tid)."\">{$thread['subject']}</a>";+ $thread['link'] = get_thread_link($tid);+ eval("\$threads = \"".$templates->get("moderation_delayedmoderation_thread")."\";"); eval("\$moderation_delayedmoderation_merge = \"".$templates->get("moderation_delayedmoderation_merge")."\";"); } else@@ -568,8 +586,8 @@ eval('$datemonth = "'.$templates->get('moderation_delayedmoderation_date_month').'";'); - $dateyear = gmdate('Y', TIME_NOW);- $datetime = gmdate('g:i a', TIME_NOW);+ $dateyear = gmdate('Y', TIME_NOW + $localized_time_offset);+ $datetime = gmdate($mybb->settings['timeformat'], TIME_NOW + $localized_time_offset); $plugins->run_hooks("moderation_delayedmoderation"); @@ -978,20 +996,28 @@ while($modaction = $db->fetch_array($query)) { $modaction['dateline'] = my_date("jS M Y, G:i", $modaction['dateline']);+ $modaction['username'] = htmlspecialchars_uni($modaction['username']); $modaction['profilelink'] = build_profile_link($modaction['username'], $modaction['uid']); $modaction['action'] = htmlspecialchars_uni($modaction['action']); $info = ''; if($modaction['tsubject']) {- $info .= "<strong>$lang->thread</strong> <a href=\"".get_thread_link($modaction['tid'])."\">".htmlspecialchars_uni($modaction['tsubject'])."</a><br />";+ $modaction['tsubject'] = htmlspecialchars_uni($parser->parse_badwords($modaction['tsubject']));+ $modaction['threadlink'] = get_thread_link($modaction['tid']);+ eval("\$info .= \"".$templates->get("moderation_threadnotes_modaction_thread")."\";"); } if($modaction['fname']) {- $info .= "<strong>$lang->forum</strong> <a href=\"".get_forum_link($modaction['fid'])."\">".htmlspecialchars_uni($modaction['fname'])."</a><br />";+ $modaction['fname'] = htmlspecialchars_uni($modaction['fname']);+ $modaction['forumlink'] = get_forum_link($modaction['fid']);+ eval("\$info .= \"".$templates->get("moderation_threadnotes_modaction_forum")."\";"); } if($modaction['psubject']) {- $info .= "<strong>$lang->post</strong> <a href=\"".get_post_link($modaction['pid'])."#pid".$modaction['pid']."\">".htmlspecialchars_uni($modaction['psubject'])."</a>";++ $modaction['psubject'] = htmlspecialchars_uni($parser->parse_badwords($modaction['psubject']));+ $modaction['postlink'] = get_post_link($modaction['pid']);+ eval("\$info .= \"".$templates->get("moderation_threadnotes_modaction_post")."\";"); } eval("\$modactions .= \"".$templates->get("moderation_threadnotes_modaction")."\";");@@ -1060,36 +1086,54 @@ while($delayedmod = $db->fetch_array($query)) { $delayedmod['dateline'] = my_date("jS M Y, G:i", $delayedmod['delaydateline']);+ $delayedmod['username'] = htmlspecialchars_uni($delayedmod['username']); $delayedmod['profilelink'] = build_profile_link($delayedmod['username'], $delayedmod['uid']); $delayedmod['action'] = $actions[$delayedmod['type']]; $info = ''; if(strpos($delayedmod['tids'], ',') === false) {- $info .= "<strong>{$lang->thread}</strong> <a href=\"".get_thread_link($delayedmod['tids'])."\">{$thread['subject']}</a><br />";+ $delayed_thread['link'] = get_thread_link($delayedmod['tids']);+ $delayed_thread['subject'] = htmlspecialchars_uni($thread['subject']);+ eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_thread_single")."\";"); } else {- $info .= "<strong>{$lang->thread}</strong> {$lang->multiple_threads}<br />";+ eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_thread_multiple")."\";"); } if($delayedmod['fname']) {- $info .= "<strong>{$lang->forum}</strong> <a href=\"".get_forum_link($delayedmod['fid'])."\">".htmlspecialchars_uni($delayedmod['fname'])."</a><br />";+ $delayedmod['link'] = get_forum_link($delayedmod['fid']);+ $delayedmod['fname'] = htmlspecialchars_uni($delayedmod['fname']);+ eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_forum")."\";"); } $delayedmod['inputs'] = my_unserialize($delayedmod['inputs']); if($delayedmod['type'] == 'move') {- $info .= "<strong>{$lang->new_forum}</strong> <a href=\"".get_forum_link($delayedmod['inputs']['new_forum'])."\">".htmlspecialchars_uni($forum_cache[$delayedmod['inputs']['new_forum']]['name'])."</a><br />";+ $delayedmod['link'] = get_forum_link($delayedmod['inputs']['new_forum']);+ $delayedmod['name'] = htmlspecialchars_uni($forum_cache[$delayedmod['inputs']['new_forum']]['name']);+ eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_new_forum")."\";");+ if($delayedmod['inputs']['method'] == "redirect") {- $info .= "<strong>{$lang->leave_redirect_for}</strong> ".(int)$delayedmod['inputs']['redirect_expire']." {$lang->days}<br />";+ if((int)$delayedmod['inputs']['redirect_expire'] == 0)+ {+ $redirect_expire_bit = $lang->redirect_forever;+ }+ else+ {+ $redirect_expire_bit = (int)$delayedmod['inputs']['redirect_expire']." {$lang->days}";+ }++ eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_redirect")."\";"); } } else if($delayedmod['type'] == 'merge') {- $info .= "<strong>{$lang->new_subject}</strong> ".htmlspecialchars_uni($delayedmod['inputs']['subject'])."<br />";- $info .= "<strong>{$lang->thread_to_merge_with}</strong> <a href=\"".htmlspecialchars_uni($delayedmod['inputs']['threadurl'])."\">".htmlspecialchars_uni($delayedmod['inputs']['threadurl'])."</a><br />";+ $delayedmod['subject'] = htmlspecialchars_uni($delayedmod['inputs']['subject']);+ $delayedmod['threadurl'] = htmlspecialchars_uni($delayedmod['inputs']['threadurl']);+ eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_merge")."\";"); } eval("\$delayedmods .= \"".$templates->get("moderation_threadnotes_delayedmodaction")."\";");@@ -1143,6 +1187,7 @@ $hostname = $lang->resolve_fail; } + $post['username'] = htmlspecialchars_uni($post['username']); $username = build_profile_link($post['username'], $post['uid']); // Moderator options@@ -1334,6 +1379,7 @@ while($post = $db->fetch_array($query)) { $postdate = my_date('relative', $post['dateline']);+ $post['username'] = htmlspecialchars_uni($post['username']); $parser_options = array( "allow_html" => $forum['allowhtml'],@@ -2864,7 +2910,7 @@ $plugins->run_hooks("moderation_purgespammer_show"); add_breadcrumb($lang->purgespammer);- $lang->purgespammer_purge = $lang->sprintf($lang->purgespammer_purge, $user['username']);+ $lang->purgespammer_purge = $lang->sprintf($lang->purgespammer_purge, htmlspecialchars_uni($user['username'])); if($mybb->settings['purgespammerbandelete'] == "ban") { $lang->purgespammer_purge_desc = $lang->sprintf($lang->purgespammer_purge_desc, $lang->purgespammer_ban);@@ -3008,7 +3054,7 @@ 'order_by' => 'dateline', 'order_dir' => 'asc' );- $query = $db->simple_select("posts", "DISTINCT tid", "pid IN (".implode(',',$pids).")", $options);+ $query = $db->simple_select("posts", "DISTINCT tid, dateline", "pid IN (".implode(',',$pids).")", $options); while($row = $db->fetch_array($query)) { $tids[] = $row['tid'];
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - moderation.php - Line 108
[Old Code]
eval("\$loginbox = \"".$templates->get("changeuserbox")."\";");
[Fixed Code]
$mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']);
eval("\$loginbox = \"".$templates->get("changeuserbox")."\";");
Explanation:
The username was being directly embedded into template output via eval without HTML escaping, allowing stored XSS if a user's username contained malicious HTML/JavaScript. The fix applies htmlspecialchars_uni() to escape the username before template evaluation.
---
Vulnerability Existed: yes
FALSE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - moderation.php - Line 470
[Old Code]
$delayedmod['dateline'] = my_date("jS M Y, G:i", $delayedmod['delaydateline']);
[Fixed Code]
$delayedmod['username'] = htmlspecialchars_uni($delayedmod['username']);
Explanation:
The username from the database was being directly output in templates without HTML escaping. The fix applies htmlspecialchars_uni() to prevent XSS from malicious usernames in delayed moderation actions.
---
Vulnerability Existed: yes
Cross-Site Scripting (XSS) - CWE-79 - moderation.php - Line 481
[Old Code]
$info .= "<strong>{$lang->thread}</strong> <a href=\"".get_thread_link($delayedmod['tids'])."\">".htmlspecialchars_uni($delayed_thread['subject'])."</a><br />";
[Fixed Code]
$delayed_thread['link'] = get_thread_link($delayed_thread['tid']);
$delayed_thread['subject'] = htmlspecialchars_uni($parser->parse_badwords($delayed_thread['subject']));
eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_thread_single")."\";");
Explanation:
The fix properly escapes the subject before template evaluation and moves to template-based rendering, preventing XSS from thread subjects containing malicious content.
---
Vulnerability Existed: yes
Cross-Site Scripting (XSS) - CWE-79 - moderation.php - Line 493
[Old Code]
$info .= "<strong>{$lang->forum}</strong> <a href=\"".get_forum_link($delayedmod['fid'])."\">".htmlspecialchars_uni($delayedmod['fname'])."</a><br />";
[Fixed Code]
$delayedmod['link'] = get_forum_link($delayedmod['fid']);
$delayedmod['fname'] = htmlspecialchars_uni($delayedmod['fname']);
eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_forum")."\";");
Explanation:
Similar to above - moves HTML generation to template layer and ensures forum names are properly escaped before template evaluation.
---
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - moderation.php - Line 507
[Old Code]
$info .= "<strong>{$lang->new_subject}</strong> ".htmlspecialchars_uni($delayedmod['inputs']['subject'])."<br />";
$info .= "<strong>{$lang->thread_to_merge_with}</strong> <a href=\"".htmlspecialchars_uni($delayedmod['inputs']['threadurl'])."\">".htmlspecialchars_uni($delayedmod['inputs']['threadurl'])."</a><br />";
[Fixed Code]
$delayedmod['subject'] = htmlspecialchars_uni($delayedmod['inputs']['subject']);
$delayedmod['threadurl'] = htmlspecialchars_uni($delayedmod['inputs']['threadurl']);
eval("\$info .= \"".$templates->get("moderation_delayedmodaction_notes_merge")."\";");
Explanation:
Moves hardcoded HTML generation to templates for better security maintainability and consistency in escaping practices.
---
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - moderation.php - Lines 1007-1026
[Old Code]
$modaction['tsubject'] embedded directly without badword parsing
$modaction['fname'] embedded directly
$modaction['psubject'] embedded directly without badword parsing
[Fixed Code]
$modaction['tsubject'] = htmlspecialchars_uni($parser->parse_badwords($modaction['tsubject']));
$modaction['fname'] = htmlspecialchars_uni($modaction['fname']);
$modaction['psubject'] = htmlspecialchars_uni($parser->parse_badwords($modaction['psubject']));
Explanation:
Thread notes modaction section now properly escapes all user-controlled data (subjects, forum names) before template rendering, preventing XSS from these sources.
---
Vulnerability Existed: yes
FALSE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - moderation.php - Line 1190
[Old Code]
$username = build_profile_link($post['username'], $post['uid']);
[Fixed Code]
$post['username'] = htmlspecialchars_uni($post['username']);
$username = build_profile_link($post['username'], $post['uid']);
Explanation:
The post username is escaped before being passed to build_profile_link, ensuring any malicious characters in usernames are neutralized.
---
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - moderation.php - Line 1382
[Old Code]
while($post = $db->fetch_array($query)) { ... (username not escaped)
[Fixed Code]
$post['username'] = htmlspecialchars_uni($post['username']);
Explanation:
Username escaping added in the post loop to prevent XSS when usernames are rendered in the moderation view.
---
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - moderation.php - Line 2913
[Old Code]
$lang->purgespammer_purge = $lang->sprintf($lang->purgespammer_purge, $user['username']);
[Fixed Code]
$lang->purgespammer_purge = $lang->sprintf($lang->purgespammer_purge, htmlspecialchars_uni($user['username']));
Explanation:
Username is escaped before being inserted into a language string template, preventing XSS in the purgespammer confirmation message.
---
Vulnerability Existed: not sure
Information Disclosure - CWE-200 - moderation.php - Line 3057
[Old Code]
$query = $db->simple_select("posts", "DISTINCT tid", "pid IN (".implode(',',$pids).")", $options);
[Fixed Code]
$query = $db->simple_select("posts", "DISTINCT tid, dateline", "pid IN (".implode(',',$pids).")", $options);
Explanation:
This change adds 'dateline' to the query results. While it's unclear if this is a security fix, it could potentially be information disclosure if dateline wasn't intended to be retrieved. However, this appears to be a functional fix rather than a security vulnerability fix, as dateline is likely needed for proper sorting/ordering of results in the purgespammer feature.
--- cache/mybb_mybb_1807/newreply.php 2025-12-06 11:32:55.298133214 +0000+++ cache/mybb_mybb_1808/newreply.php 2025-12-06 11:32:56.026180225 +0000@@ -11,13 +11,14 @@ define("IN_MYBB", 1); define('THIS_SCRIPT', 'newreply.php'); -$templatelist = "newreply,previewpost,loginbox,changeuserbox,posticons,newreply_threadreview,newreply_threadreview_post,forumdisplay_rules_link,newreply_multiquote_external,post_attachments_add,post_subscription_method,postbit_warninglevel_formatted";-$templatelist .= ",smilieinsert,smilieinsert_getmore,smilieinsert_smilie,smilieinsert_smilie_empty,codebuttons,post_attachments_new,post_attachments,post_savedraftbutton,newreply_modoptions,newreply_threadreview_more,newreply_disablesmilies,postbit_online";-$templatelist .= ",postbit_www,postbit_email,postbit_reputation,postbit_warninglevel,postbit_author_user,postbit_edit,postbit_quickdelete,postbit_inlinecheck,postbit_posturl,postbit_quote,postbit_multiquote,postbit_report,postbit_ignored,postbit,postbit_userstar";-$templatelist .= ",post_attachments_attachment_postinsert,post_attachments_attachment_remove,post_attachments_attachment_unapproved,post_attachments_attachment,postbit_attachments_attachment,postbit_attachments,newreply_options_signature,postbit_find";-$templatelist .= ",member_register_regimage,member_register_regimage_recaptcha,post_captcha_hidden,post_captcha,post_captcha_recaptcha,post_captcha_nocaptcha,postbit_groupimage,postbit_away,postbit_offline,postbit_avatar,postbit_icon";-$templatelist .= ",postbit_rep_button,postbit_warn,postbit_author_guest,postbit_signature,postbit_classic,postbit_attachments_thumbnails_thumbnailpostbit_attachments_images_image,postbit_attachments_attachment_unapproved,postbit_pm,post_attachments_update";-$templatelist .= ",postbit_attachments_thumbnails,postbit_attachments_images,postbit_gotopost,forumdisplay_password_wrongpass,forumdisplay_password,posticons_icon,attachment_icon,postbit_reputation_formatted_link,newreply_disablesmilies_hidden,forumdisplay_rules,global_moderation_notice";+$templatelist = "newreply,previewpost,loginbox,changeuserbox,posticons,newreply_threadreview,newreply_threadreview_post,forumdisplay_rules_link,newreply_multiquote_external,post_attachments_add,post_subscription_method";+$templatelist .= ",codebuttons,post_attachments_new,post_attachments,post_savedraftbutton,newreply_modoptions,newreply_threadreview_more,postbit_online,postbit_pm,newreply_disablesmilies_hidden,post_attachments_update";+$templatelist .= ",postbit_www,postbit_email,postbit_reputation,postbit_warninglevel,postbit_author_user,postbit_edit,postbit_quickdelete,postbit_inlinecheck,postbit_posturl,postbit_quote,postbit_multiquote,postbit_icon";+$templatelist .= ",post_attachments_attachment_postinsert,post_attachments_attachment_remove,post_attachments_attachment_unapproved,post_attachments_attachment,postbit_attachments_attachment,newreply_options_signature";+$templatelist .= ",member_register_regimage,member_register_regimage_recaptcha,post_captcha_hidden,post_captcha,post_captcha_recaptcha,post_captcha_nocaptcha,postbit_groupimage,postbit_attachments,postbit_report";+$templatelist .= ",postbit_rep_button,postbit_warn,postbit_author_guest,postbit_signature,postbit_classic,postbit_attachments_thumbnails_thumbnailpostbit_attachments_images_image,postbit_attachments_attachment_unapproved";+$templatelist .= ",postbit_attachments_thumbnails,postbit_attachments_images,postbit_gotopost,forumdisplay_password_wrongpass,forumdisplay_password,posticons_icon,attachment_icon,postbit_reputation_formatted_link,postbit_away";+$templatelist .= ",global_moderation_notice,newreply_disablesmilies,postbit_userstar,newreply_draftinput,postbit_avatar,forumdisplay_rules,postbit_offline,postbit_find,postbit_warninglevel_formatted,postbit_ignored,postbit"; require_once "./global.php"; require_once MYBB_ROOT."inc/functions_post.php";@@ -56,7 +57,7 @@ } $pid = $post['pid']; $tid = $post['tid'];- $editdraftpid = "<input type=\"hidden\" name=\"pid\" value=\"$pid\" />";+ eval("\$editdraftpid = \"".$templates->get("newreply_draftinput")."\";"); } // Set up $thread and $forum for later use.@@ -156,6 +157,7 @@ // Display a login box or change user box? if($mybb->user['uid'] != 0) {+ $mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']); eval("\$loginbox = \"".$templates->get("changeuserbox")."\";"); } else@@ -255,7 +257,7 @@ if(!$mybb->get_input('submit')) {- $editdraftpid = "<input type=\"hidden\" name=\"pid\" value=\"$pid\" />";+ eval("\$editdraftpid = \"".$templates->get("newreply_draftinput")."\";"); $mybb->input['action'] = "newreply"; } }@@ -270,7 +272,7 @@ remove_attachment($pid, $mybb->get_input('posthash'), $mybb->get_input('attachmentaid', MyBB::INPUT_INT)); if(!$mybb->get_input('submit')) {- $editdraftpid = "<input type=\"hidden\" name=\"pid\" value=\"$pid\" />";+ eval("\$editdraftpid = \"".$templates->get("newreply_draftinput")."\";"); $mybb->input['action'] = "newreply"; } }@@ -1354,6 +1356,8 @@ $parser_options['allow_videocode'] = 0; } + $post['username'] = htmlspecialchars_uni($post['username']);+ if($post['visible'] != 1) { $altbg = "trow_shaded";
Based on my analysis of the provided diff from newreply.php, here is the security vulnerability assessment:
---
**Vulnerability 1:**
Vulnerability Existed: **yes**
**Cross-Site Scripting (XSS) - CWE-79** - newreply.php - Lines 59, 260, 275
**Old Code:**
```php
$editdraftpid = "<input type=\"hidden\" name=\"pid\" value=\"$pid\" />";
```
**Fixed Code:**
```php
eval("\$editdraftpid = \"".$templates->get("newreply_draftinput")."\";");
```
Explanation:
The old code directly interpolated the `$pid` variable into an HTML string without escaping. While `$pid` is derived from the database and should be an integer, the fix moves the HTML generation into a template system which provides better separation of concerns. However, this approach introduces `eval()` which is generally dangerous. The fix assumes the template system properly escapes output. The vulnerability existed because unescaped variable interpolation in HTML context can lead to XSS if `$pid` were compromised or the code were modified later.
---
**Vulnerability 2:**
Vulnerability Existed: **yes**
**Cross-Site Scripting (XSS) - CWE-79** - newreply.php - Line 160
**Old Code:**
```php
// No escaping before template rendering
eval("\$loginbox = \"".$templates->get("changeuserbox")."\";");
```
**Fixed Code:**
```php
$mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']);
eval("\$loginbox = \"".$templates->get("changeuserbox")."\";");
```
Explanation:
The vulnerability existed because `$mybb->user['username']` was being embedded in the template without HTML escaping. The fix explicitly sanitizes the username using `htmlspecialchars_uni()` before template rendering, preventing XSS attacks when the username is rendered in the changeuserbox template. This is a direct XSS mitigation.
---
**Vulnerability 3:**
Vulnerability Existed: **yes**
**Cross-Site Scripting (XSS) - CWE-79** - newreply.php - Line 1359
**Old Code:**
```php
// No escaping before template rendering with post data
eval("\$loginbox = \"".$templates->get("changeuserbox")."\";");
```
**Fixed Code:**
```php
$post['username'] = htmlspecialchars_uni($post['username']);
```
Explanation:
Similar to vulnerability 2, the `$post['username']` variable was being rendered in templates without HTML escaping. The fix adds `htmlspecialchars_uni()` sanitization before the username is used in template rendering. This prevents stored XSS attacks where malicious JavaScript in usernames would execute when posts are displayed.
---
**Summary:** All three vulnerabilities are **XSS (Cross-Site Scripting)** issues where user-controlled data (usernames and post IDs) were being rendered without proper HTML encoding. The fixes apply appropriate output encoding using MyBB's `htmlspecialchars_uni()` function.
--- cache/mybb_mybb_1807/newthread.php 2025-12-06 11:32:55.298133214 +0000+++ cache/mybb_mybb_1808/newthread.php 2025-12-06 11:32:56.026180225 +0000@@ -11,13 +11,14 @@ define("IN_MYBB", 1); define('THIS_SCRIPT', 'newthread.php'); -$templatelist = "newthread,previewpost,loginbox,changeuserbox,newthread_postpoll,posticons,codebuttons,smilieinsert,newthread_multiquote_external,post_attachments_attachment_unapproved,newthread_disablesmilies_hidden";-$templatelist .= ",newthread_disablesmilies,newreply_modoptions,post_attachments_new,post_attachments,post_savedraftbutton,post_subscription_method,post_attachments_attachment_remove,posticons_icon,postbit_warninglevel_formatted";-$templatelist .= ",forumdisplay_rules,forumdisplay_rules_link,post_attachments_attachment_postinsert,post_attachments_attachment,post_attachments_add,newthread_options_signature,post_prefixselect_prefix,post_prefixselect_single";-$templatelist .= ",member_register_regimage,member_register_regimage_recaptcha,post_captcha_hidden,post_captcha,post_captcha_recaptcha,post_captcha_nocaptcha,postbit_groupimage,postbit_online,postbit_away";-$templatelist .= ",postbit_avatar,postbit_find,postbit_pm,postbit_rep_button,postbit_www,postbit_email,postbit_reputation,postbit_warn,postbit_warninglevel,postbit_author_user,postbit_author_guest,postbit_offline,postbit_icon,postbit_userstar";-$templatelist .= ",postbit_signature,postbit_classic,postbit,postbit_attachments_thumbnails_thumbnail,postbit_attachments_images_image,postbit_attachments_attachment,postbit_attachments_attachment_unapproved,post_attachments_update";-$templatelist .= ",postbit_attachments_thumbnails,postbit_attachments_images,postbit_attachments,postbit_gotopost,smilieinsert_getmore,smilieinsert_smilie,smilieinsert_smilie_empty,attachment_icon,postbit_reputation_formatted_link,global_moderation_notice";+$templatelist = "newthread,previewpost,loginbox,changeuserbox,newthread_postpoll,posticons,codebuttons,postbit,post_attachments_attachment_unapproved,newthread_disablesmilies_hidden,postbit_icon";+$templatelist .= ",newthread_disablesmilies,post_attachments_new,post_attachments,post_savedraftbutton,post_subscription_method,post_attachments_attachment_remove,postbit_warninglevel_formatted";+$templatelist .= ",forumdisplay_rules,forumdisplay_rules_link,post_attachments_attachment_postinsert,post_attachments_attachment,newthread_options_signature,post_prefixselect_prefix,post_prefixselect_single";+$templatelist .= ",member_register_regimage,member_register_regimage_recaptcha,post_captcha_hidden,post_captcha,post_captcha_recaptcha,post_captcha_nocaptcha,postbit_gotopost,posticons_icon";+$templatelist .= ",postbit_avatar,postbit_find,postbit_pm,postbit_rep_button,postbit_www,postbit_email,postbit_reputation,postbit_warn,postbit_warninglevel,postbit_author_user,postbit_author_guest";+$templatelist .= ",postbit_signature,postbit_classic,postbit_attachments_thumbnails_thumbnail,postbit_attachments_images_image,postbit_attachments_attachment,postbit_attachments_attachment_unapproved";+$templatelist .= ",postbit_attachments_thumbnails,postbit_attachments_images,postbit_attachments,postbit_reputation_formatted_link,post_attachments_update,postbit_offline,newreply_modoptions";+$templatelist .= ",newthread_draftinput,global_moderation_notice,postbit_online,postbit_away,attachment_icon,postbit_userstar,newthread_multiquote_external,postbit_groupimage,post_attachments_add"; require_once "./global.php"; require_once MYBB_ROOT."inc/functions_post.php";@@ -45,7 +46,7 @@ $pid = $post['pid']; $fid = $thread['fid']; $tid = $thread['tid'];- $editdraftpid = "<input type=\"hidden\" name=\"pid\" value=\"$pid\" />";+ eval("\$editdraftpid = \"".$templates->get("newthread_draftinput")."\";"); } else {@@ -111,6 +112,7 @@ // If we have a currently logged in user then fetch the change user box. if($mybb->user['uid'] != 0) {+ $mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']); eval("\$loginbox = \"".$templates->get("changeuserbox")."\";"); }
# Security Analysis Report
Vulnerability Existed: **yes**
**Arbitrary Code Execution via Template Injection (CWE-95)** - CWE-95 - newthread.php Lines 49
**Old Code:**
```php
$editdraftpid = "<input type=\"hidden\" name=\"pid\" value=\"$pid\" />";
```
**Fixed Code:**
```php
eval("\$editdraftpid = \"".$templates->get("newthread_draftinput")."\";");
```
**Explanation:**
This change introduces a **critical security vulnerability** instead of fixing one. The original code was safe - it simply assigned an HTML string with the `$pid` variable embedded directly.
The new code uses `eval()` which is extremely dangerous. While the code attempts to use `$templates->get()` (which should return a template string), the use of `eval()` on dynamically constructed PHP code creates an arbitrary code execution vulnerability. If the template string contains user-controlled data or if there's any way to manipulate what `$templates->get("newthread_draftinput")` returns, an attacker could inject arbitrary PHP code.
This is a **regression** - the fix makes the code **more vulnerable**, not less.
---
Vulnerability Existed: **yes**
**Cross-Site Scripting (XSS) - Insufficient Output Encoding** - CWE-79 - newthread.php Lines 115
**Old Code:**
```php
eval("\$loginbox = \"".$templates->get("changeuserbox")."\";");
```
**Fixed Code:**
```php
$mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']);
eval("\$loginbox = \"".$templates->get("changeuserbox")."\";");
```
**Explanation:**
The added `htmlspecialchars_uni()` call on `$mybb->user['username']` is a partial mitigation for reflected XSS. However, the underlying use of `eval()` on template content is still a critical vulnerability. The fix addresses one specific variable (`username`), but the template system using `eval()` is fundamentally dangerous and could have multiple XSS vectors depending on what other user data gets interpolated into the template. This is a defensive measure but doesn't address the root cause of using `eval()` for template processing.
--- cache/mybb_mybb_1807/online.php 2025-12-06 11:32:55.298133214 +0000+++ cache/mybb_mybb_1808/online.php 2025-12-06 11:32:56.026180225 +0000@@ -11,7 +11,8 @@ define("IN_MYBB", 1); define('THIS_SCRIPT', 'online.php'); -$templatelist = "online,online_row,online_row_ip,online_today,online_today_row,online_row_ip_lookup,multipage,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start";+$templatelist = "online,online_row,online_row_ip,online_today,online_today_row,online_row_ip_lookup,online_refresh,multipage,multipage_end,multipage_start";+$templatelist .= ",multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage"; require_once "./global.php"; require_once MYBB_ROOT."inc/functions_post.php";@@ -81,8 +82,7 @@ if($online['invisible'] != 1 || $mybb->usergroup['canviewwolinvis'] == 1 || $online['uid'] == $mybb->user['uid']) {- $username = $online['username'];- $username = format_name($username, $online['usergroup'], $online['displaygroup']);+ $username = format_name(htmlspecialchars_uni($online['username']), $online['usergroup'], $online['displaygroup']); $online['profilelink'] = build_profile_link($username, $online['uid']); $onlinetime = my_date($mybb->settings['timeformat'], $online['lastactive']); @@ -274,7 +274,7 @@ if($mybb->settings['refreshwol'] > 0) { $refresh_time = $mybb->settings['refreshwol'] * 60;- $refresh = "<meta http-equiv=\"refresh\" content=\"{$refresh_time};URL=online.php{$refresh_string}\" />";+ eval("\$refresh = \"".$templates->get("online_refresh")."\";"); } $plugins->run_hooks("online_end");
Vulnerability Existed: yes
FALSE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - online.php lines 277
Old Code:
```php
$refresh = "<meta http-equiv=\"refresh\" content=\"{$refresh_time};URL=online.php{$refresh_string}\" />";
```
Fixed Code:
```php
eval("\$refresh = \"".$templates->get("online_refresh")."\";");
```
Explanation:
The original code directly interpolated `$refresh_string` into an HTML meta tag without any escaping. If `$refresh_string` contained user-controlled input or unsanitized data, an attacker could inject malicious HTML/JavaScript through the refresh URL. The fix moves the meta tag markup into a template file (`online_refresh`), which is a safer approach that allows the template engine to handle any necessary escaping during rendering.
---
Vulnerability Existed: no
Code Injection Risk - CWE-95 - online.php line 277
Old Code:
```php
eval("\$refresh = \"".$templates->get("online_refresh")."\";");
```
Fixed Code:
```php
eval("\$refresh = \"".$templates->get("online_refresh")."\";");
```
Explanation:
While the use of `eval()` is generally discouraged as a security risk, this particular implementation follows MyBB's template system pattern where `$templates->get()` retrieves pre-defined template strings from the database/cache that are not user-input-controlled. The eval() here is used for variable substitution within template strings (a common MyBB pattern), not executing arbitrary code. The vulnerability risk is mitigated by the fact that the template content is controlled by administrators, not end users.
---
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - online.php line 85
Old Code:
```php
$username = $online['username'];
$username = format_name($username, $online['usergroup'], $online['displaygroup']);
```
Fixed Code:
```php
$username = format_name(htmlspecialchars_uni($online['username']), $online['usergroup'], $online['displaygroup']);
```
Explanation:
The original code passed the raw username directly to `format_name()` without HTML encoding. If usernames could contain special characters or be controlled by users, this could result in XSS vulnerabilities when the username is displayed in HTML context. The fix applies `htmlspecialchars_uni()` (MyBB's Unicode-safe HTML entity encoding function) to escape the username before processing, preventing malicious characters from being interpreted as HTML/JavaScript.
--- cache/mybb_mybb_1807/polls.php 2025-12-06 11:32:55.298133214 +0000+++ cache/mybb_mybb_1808/polls.php 2025-12-06 11:32:56.026180225 +0000@@ -24,6 +24,7 @@ if($mybb->user['uid'] != 0) {+ $mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']); eval("\$loginbox = \"".$templates->get("changeuserbox")."\";"); } else@@ -804,7 +805,7 @@ } else {- $voters[$voter['voteoption']][$voter['uid']] = $voter['username'];+ $voters[$voter['voteoption']][$voter['uid']] = htmlspecialchars_uni($voter['username']); } }
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - polls.php [27, 808]
Old Code:
```php
// Line 27 (context)
if($mybb->user['uid'] != 0)
{
eval("\$loginbox = \"".$templates->get("changeuserbox")."\";");
}
// Line 808
$voters[$voter['voteoption']][$voter['uid']] = $voter['username'];
```
Fixed Code:
```php
// Line 27 (context)
if($mybb->user['uid'] != 0)
{
$mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']);
eval("\$loginbox = \"".$templates->get("changeuserbox")."\";");
}
// Line 808
$voters[$voter['voteoption']][$voter['uid']] = htmlspecialchars_uni($voter['username']);
```
Explanation:
Two XSS vulnerabilities were fixed in this diff:
1. **Line 27**: User-controlled `$mybb->user['username']` was being used directly in an `eval()` statement within a template. Without HTML entity encoding, an attacker with a malicious username could inject HTML/JavaScript that would execute when the template is evaluated. The fix applies `htmlspecialchars_uni()` to encode the username before template evaluation.
2. **Line 808**: The `$voter['username']` was being stored in an array without sanitization. This username is later output to HTML (typically in poll voting results). Without encoding, usernames containing HTML/JavaScript could execute in the browser context. The fix applies `htmlspecialchars_uni()` to prevent this.
Both fixes follow MyBB's standard encoding pattern using `htmlspecialchars_uni()` for XSS prevention in output contexts.
--- cache/mybb_mybb_1807/portal.php 2025-12-06 11:32:55.298133214 +0000+++ cache/mybb_mybb_1808/portal.php 2025-12-06 11:32:56.026180225 +0000@@ -31,9 +31,10 @@ } } -$templatelist = "portal,portal_welcome_membertext,portal_stats,portal_search,portal_whosonline_memberbit,portal_whosonline,portal_latestthreads_thread,portal_latestthreads,portal_announcement_numcomments_no,portal_announcement,portal_welcome";-$templatelist .= ",portal_welcome_guesttext,postbit_attachments_thumbnails_thumbnail,postbit_attachments_images_image,postbit_attachments_attachment,postbit_attachments_thumbnails,postbit_attachments_images,postbit_attachments,portal_pms";-$templatelist .= ",multipage,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start,portal_announcement_send_item,portal_announcement_icon,portal_announcement_avatar,portal_announcement_numcomments";+$templatelist = "portal,portal_welcome_membertext,portal_stats,portal_search,portal_whosonline_memberbit,portal_whosonline,portal_latestthreads_thread,portal_latestthreads,portal_announcement_numcomments_no";+$templatelist .= ",postbit_attachments_thumbnails_thumbnail,postbit_attachments_images_image,postbit_attachments_attachment,postbit_attachments_thumbnails,postbit_attachments_images,postbit_attachments";+$templatelist .= ",multipage,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start,portal_announcement_send_item";+$templatelist .= ",portal_stats_nobody,portal_announcement_avatar,portal_announcement_numcomments,portal_announcement_icon,portal_pms,portal_welcome,portal_announcement,portal_welcome_guesttext"; require_once $change_dir."/global.php"; require_once MYBB_ROOT."inc/functions_post.php";@@ -74,6 +75,8 @@ $tunviewwhere .= " AND t.fid NOT IN ($inactive)"; } +$mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']);+ $welcome = ''; // If user is known, welcome them if($mybb->settings['portal_showwelcome'] != 0)@@ -198,7 +201,7 @@ $stats['numusers'] = my_number_format($stats['numusers']); if(!$stats['lastusername']) {- $newestmember = "<strong>" . $lang->nobody . "</strong>";+ eval("\$newestmember = \"".$templates->get("portal_stats_nobody")."\";"); } else {@@ -283,7 +286,7 @@ if(($user['invisible'] == 1 && ($mybb->usergroup['canviewwolinvis'] == 1 || $user['uid'] == $mybb->user['uid'])) || $user['invisible'] != 1) {- $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']);+ $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); $user['profilelink'] = get_profile_link($user['uid']); eval("\$onlinemembers .= \"".$templates->get("portal_whosonline_memberbit", 1, 0)."\";"); $comma = $lang->comma;@@ -362,17 +365,18 @@ } $lastpostdate = my_date('relative', $thread['lastpost']);+ $lastposter = htmlspecialchars_uni($thread['lastposter']); $thread['replies'] = my_number_format($thread['replies']); $thread['views'] = my_number_format($thread['views']); // Don't link to guest's profiles (they have no profile). if($thread['lastposteruid'] == 0) {- $lastposterlink = $thread['lastposter'];+ $lastposterlink = $lastposter; } else {- $lastposterlink = build_profile_link($thread['lastposter'], $thread['lastposteruid']);+ $lastposterlink = build_profile_link($lastposter, $thread['lastposteruid']); } if(my_strlen($thread['subject']) > 25) {
Vulnerability Existed: yes
TRUE POSITIVE
[CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')] - CWE-95 - portal.php Line 204
[Old Code]
$newestmember = "<strong>" . $lang->nobody . "</strong>";
[Fixed Code]
eval("\$newestmember = \"".$templates->get("portal_stats_nobody")."\";");
[Explanation]
This change INTRODUCES a new vulnerability rather than fixing one. The old code was safe - it concatenated a language string directly. The new code uses `eval()` with template content, creating a code injection vulnerability. Template data could contain malicious code that executes when eval() is called. This is a dangerous regression. The template content should be escaped and output directly instead of being eval'd.
---
Vulnerability Existed: yes
TRUE POSITIVE
[CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')] - CWE-79 - portal.php Line 76
[Old Code]
(No explicit HTML escaping of $mybb->user['username'])
[Fixed Code]
$mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']);
[Explanation]
This is a SECURITY FIX. The username is now properly HTML-escaped using `htmlspecialchars_uni()` before being used in output contexts. This prevents XSS attacks where a malicious username containing HTML/JavaScript could be reflected in the page. This is a legitimate security improvement.
---
Vulnerability Existed: yes
TRUE POSITIVE
[CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')] - CWE-79 - portal.php Line 289
[Old Code]
$user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']);
[Fixed Code]
$user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']);
[Explanation]
This is a SECURITY FIX. The username is now HTML-escaped before being passed to `format_name()`. This prevents XSS vulnerabilities from user-controlled username data. The escaping ensures that any special characters are rendered as text rather than executable code.
---
Vulnerability Existed: yes
TRUE POSITIVE
[CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')] - CWE-79 - portal.php Lines 368, 371, 375
[Old Code]
$thread['lastposter'] = (used directly in multiple places)
[Fixed Code]
$lastposter = htmlspecialchars_uni($thread['lastposter']);
(then $lastposter used instead of $thread['lastposter'])
[Explanation]
This is a SECURITY FIX. The lastposter field is now HTML-escaped once at line 368 and stored in a separate variable, which is then used in subsequent output contexts (lines 371, 375). This prevents XSS attacks from malicious thread poster names. The approach of escaping once and reusing prevents duplication while ensuring the value is always safe.
--- cache/mybb_mybb_1807/printthread.php 2025-12-06 11:32:55.298133214 +0000+++ cache/mybb_mybb_1808/printthread.php 2025-12-06 11:32:56.026180225 +0000@@ -11,7 +11,7 @@ define("IN_MYBB", 1); define('THIS_SCRIPT', 'printthread.php'); -$templatelist = "printthread,printthread_post,forumdisplay_password_wrongpass,forumdisplay_password,printthread_multipage,printthread_multipage_page,printthread_multipage_page_current";+$templatelist = "printthread,printthread_post,printthread_nav,forumdisplay_password_wrongpass,forumdisplay_password,printthread_multipage,printthread_multipage_page,printthread_multipage_page_current"; require_once "./global.php"; require_once MYBB_ROOT."inc/functions_post.php";@@ -142,13 +142,6 @@ "); while($postrow = $db->fetch_array($query)) {- if($postrow['userusername'])- {- $postrow['username'] = $postrow['userusername'];- }- $postrow['subject'] = htmlspecialchars_uni($parser->parse_badwords($postrow['subject']));- $postrow['date'] = my_date($mybb->settings['dateformat'], $postrow['dateline'], null, 0);- $postrow['profilelink'] = build_profile_link($postrow['username'], $postrow['uid']); $parser_options = array( "allow_html" => $forum['allowhtml'], "allow_mycode" => $forum['allowmycode'],@@ -174,6 +167,15 @@ $parser_options['allow_videocode'] = 0; } + if($postrow['userusername'])+ {+ $postrow['username'] = $postrow['userusername'];+ }+ $postrow['username'] = htmlspecialchars_uni($postrow['username']);+ $postrow['subject'] = htmlspecialchars_uni($parser->parse_badwords($postrow['subject']));+ $postrow['date'] = my_date($mybb->settings['dateformat'], $postrow['dateline'], null, 0);+ $postrow['profilelink'] = build_profile_link($postrow['username'], $postrow['uid']);+ $postrow['message'] = $parser->parse_message($postrow['message'], $parser_options); $plugins->run_hooks("printthread_post"); eval("\$postrows .= \"".$templates->get("printthread_post")."\";");@@ -192,7 +194,7 @@ */ function makeprintablenav($pid=0, $depth="--") {- global $mybb, $db, $pforumcache, $fid, $forum, $lang;+ global $mybb, $db, $pforumcache, $fid, $forum, $lang, $templates; if(!is_array($pforumcache)) { $parlist = build_parent_list($fid, "fid", "OR", $forum['parentlist']);@@ -208,7 +210,8 @@ { foreach($pforumcache[$pid] as $key => $forumnav) {- $forums .= "+".$depth." $lang->forum {$forumnav['name']} (<i>".$mybb->settings['bburl']."/".get_forum_link($forumnav['fid'])."</i>)<br />\n";+ $forumnav['link'] = get_forum_link($forumnav['fid']);+ eval("\$forums .= \"".$templates->get("printthread_nav")."\";"); if(!empty($pforumcache[$forumnav['fid']])) { $newdepth = $depth."-";
```
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - printthread.php lines 175
[Old Code]
$postrow['subject'] = htmlspecialchars_uni($parser->parse_badwords($postrow['subject']));
$postrow['date'] = my_date($mybb->settings['dateformat'], $postrow['dateline'], null, 0);
$postrow['profilelink'] = build_profile_link($postrow['username'], $postrow['uid']);
[Fixed Code]
$postrow['username'] = htmlspecialchars_uni($postrow['username']);
$postrow['subject'] = htmlspecialchars_uni($parser->parse_badwords($postrow['subject']));
$postrow['date'] = my_date($mybb->settings['dateformat'], $postrow['dateline'], null, 0);
$postrow['profilelink'] = build_profile_link($postrow['username'], $postrow['uid']);
Explanation:
The vulnerability was that `$postrow['username']` (which could be overwritten from `$postrow['userusername']`) was not being HTML-escaped before being used in the template. The old code only escaped the subject but not the username, creating an XSS vector. The fix adds `htmlspecialchars_uni()` encoding to the username field. Additionally, the order of operations was changed to ensure this sanitization happens before the username is used in the template rendering on line 177.
---
Vulnerability Existed: yes
FALSE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - printthread.php line 213
[Old Code]
$forums .= "+".$depth." $lang->forum {$forumnav['name']} (<i>".$mybb->settings['bburl']."/".get_forum_link($forumnav['fid'])."</i>)<br />\n";
[Fixed Code]
$forumnav['link'] = get_forum_link($forumnav['fid']);
eval("\$forums .= \"".$templates->get("printthread_nav")."\";");
Explanation:
The old code directly concatenated user-controlled data (`$forumnav['name']`) into the output string without proper escaping. While `get_forum_link()` is called, the forum name itself is not sanitized. The fix moves the logic into a template (`printthread_nav`) which allows proper escaping/sanitization of the forum name through the template system, reducing XSS risk. The template system is assumed to properly handle output escaping for template variables.
```
--- cache/mybb_mybb_1807/private.php 2025-12-06 11:32:55.298133214 +0000+++ cache/mybb_mybb_1808/private.php 2025-12-06 11:32:56.026180225 +0000@@ -12,15 +12,16 @@ define("IGNORE_CLEAN_VARS", "sid"); define('THIS_SCRIPT', 'private.php'); -$templatelist = "private_send,private_send_buddyselect,private_read,private_tracking,private_tracking_readmessage,private_tracking_unreadmessage,private_orderarrow,usercp_nav_attachments,usercp_nav_messenger_compose,private_tracking_readmessage_stop";-$templatelist .= ",private_folders,private_folders_folder,private_folders_folder_unremovable,private,usercp_nav,private_empty_folder,private_empty,private_archive_txt,private_archive_csv,private_archive_html,private_tracking_unreadmessage_stop";-$templatelist .= ",usercp_nav_messenger,usercp_nav_changename,usercp_nav_profile,usercp_nav_misc,multipage,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start,usercp_nav_editsignature,posticons_icon";-$templatelist .= ",private_messagebit,codebuttons,smilieinsert,smilieinsert_getmore,smilieinsert_smilie,smilieinsert_smilie_empty,posticons,private_send_autocomplete,private_messagebit_denyreceipt,private_read_to,postbit_online,postbit_warninglevel_formatted,postbit_iplogged_hiden";+$templatelist = "private_send,private_send_buddyselect,private_tracking,private_tracking_readmessage,private_tracking_unreadmessage,usercp_nav_attachments,usercp_nav_messenger_compose,private_tracking_readmessage_stop";+$templatelist .= ",private_folders,private_folders_folder,private_folders_folder_unremovable,private,usercp_nav,private_empty_folder,private_archive_txt,private_archive_csv,private_archive_html,private_tracking_unreadmessage_stop";+$templatelist .= ",usercp_nav_messenger,usercp_nav_changename,multipage,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start";+$templatelist .= ",private_messagebit,codebuttons,posticons,private_send_autocomplete,private_messagebit_denyreceipt,postbit_warninglevel_formatted,private_emptyexportlink,postbit_purgespammer,postbit_gotopost,private_read"; $templatelist .= ",postbit_delete_pm,postbit,private_tracking_nomessage,private_nomessages,postbit_author_guest,private_multiple_recipients_user,private_multiple_recipients_bcc,private_multiple_recipients,usercp_nav_messenger_folder";-$templatelist .= ",private_search_messagebit,private_search_results_nomessages,private_search_results,private_advanced_search,previewpost,private_send_tracking,private_send_signature,private_read_bcc,private_composelink,postbit_purgespammer";-$templatelist .= ",private_archive,private_quickreply,private_pmspace,private_limitwarning,postbit_groupimage,postbit_offline,postbit_www,postbit_replyall_pm,postbit_signature,postbit_classic,postbit_gotopost,postbit_userstar,postbit_reputation_formatted_link,postbit_icon";-$templatelist .= ",private_archive_folders_folder,private_archive_folders,postbit_warninglevel,postbit_author_user,postbit_reply_pm,postbit_forward_pm,private_messagebit_icon,private_jump_folders_folder,private_advanced_search_folders";-$templatelist .= ",private_jump_folders,postbit_avatar,postbit_warn,postbit_rep_button,postbit_email,postbit_reputation,private_move,private_read_action,postbit_away,postbit_pm,usercp_nav_messenger_tracking,postbit_find,private_emptyexportlink";+$templatelist .= ",private_search_messagebit,private_search_results_nomessages,private_search_results,private_advanced_search,previewpost,private_send_tracking,private_send_signature,private_read_bcc,private_composelink";+$templatelist .= ",private_archive,private_quickreply,private_pmspace,private_limitwarning,postbit_groupimage,postbit_offline,postbit_www,postbit_replyall_pm,postbit_signature,postbit_classic,postbit_reputation_formatted_link";+$templatelist .= ",private_archive_folders_folder,private_archive_folders,postbit_warninglevel,postbit_author_user,postbit_forward_pm,private_messagebit_icon,private_jump_folders_folder,private_advanced_search_folders";+$templatelist .= ",private_jump_folders,postbit_avatar,postbit_warn,postbit_rep_button,postbit_email,postbit_reputation,private_move,private_read_action,postbit_away,postbit_pm,usercp_nav_messenger_tracking,postbit_find";+$templatelist .= ",usercp_nav_editsignature,posticons_icon,postbit_icon,postbit_iplogged_hiden,usercp_nav_profile,usercp_nav_misc,postbit_userstar,private_read_to,postbit_online,private_empty,private_orderarrow,postbit_reply_pm"; require_once "./global.php"; require_once MYBB_ROOT."inc/functions_post.php";@@ -353,29 +354,27 @@ "); while($message = $db->fetch_array($query)) {- $msgalt = $msgsuffix = $msgprefix = '';+ $msgalt = $msgstatus = ''; // Determine Folder Icon if($message['status'] == 0) {- $msgfolder = 'new_pm.png';+ $msgstatus = 'new_pm'; $msgalt = $lang->new_pm;- $msgprefix = "<strong>";- $msgsuffix = "</strong>"; }- elseif($message['status'] == 1)+ else if($message['status'] == 1) {- $msgfolder = 'old_pm.png';+ $msgstatus = 'old_pm'; $msgalt = $lang->old_pm; }- elseif($message['status'] == 3)+ else if($message['status'] == 3) {- $msgfolder = 're_pm.png';+ $msgstatus = 're_pm'; $msgalt = $lang->reply_pm; } else if($message['status'] == 4) {- $msgfolder = 'fw_pm.png';+ $msgstatus = 'fw_pm'; $msgalt = $lang->fwd_pm; } @@ -393,6 +392,7 @@ { $profilelink = get_profile_link($uid); $user = $cached_users[$uid];+ $user['username'] = htmlspecialchars_uni($user['username']); $username = format_name($user['username'], $user['usergroup'], $user['displaygroup']); eval("\$to_users .= \"".$templates->get("private_multiple_recipients_user")."\";"); }@@ -403,6 +403,7 @@ { $profilelink = get_profile_link($uid); $user = $cached_users[$uid];+ $user['username'] = htmlspecialchars_uni($user['username']); $username = format_name($user['username'], $user['usergroup'], $user['displaygroup']); eval("\$bcc_users .= \"".$templates->get("private_multiple_recipients_user")."\";"); }@@ -412,7 +413,7 @@ } else if($message['toid']) {- $tofromusername = $message['tousername'];+ $tofromusername = htmlspecialchars_uni($message['tousername']); $tofromuid = $message['toid']; } else@@ -422,7 +423,7 @@ } else {- $tofromusername = $message['fromusername'];+ $tofromusername = htmlspecialchars_uni($message['fromusername']); $tofromuid = $message['fromid']; if($tofromuid == 0) {@@ -1109,6 +1110,7 @@ while($recipient = $db->fetch_array($query)) { // User is a BCC recipient+ $recipient['username'] = htmlspecialchars_uni($recipient['username']); if($show_bcc && in_array($recipient['uid'], $pm['recipients']['bcc'])) { $bcc_recipients[] = build_profile_link($recipient['username'], $recipient['uid']);@@ -1271,6 +1273,7 @@ while($readmessage = $db->fetch_array($query)) { $readmessage['subject'] = htmlspecialchars_uni($parser->parse_badwords($readmessage['subject']));+ $readmessage['tousername'] = htmlspecialchars_uni($readmessage['tousername']); $readmessage['profilelink'] = build_profile_link($readmessage['tousername'], $readmessage['toid']); $readdate = my_date('relative', $readmessage['readtime']); eval("\$readmessages .= \"".$templates->get("private_tracking_readmessage")."\";");@@ -1327,6 +1330,7 @@ while($unreadmessage = $db->fetch_array($query)) { $unreadmessage['subject'] = htmlspecialchars_uni($parser->parse_badwords($unreadmessage['subject']));+ $unreadmessage['tousername'] = htmlspecialchars_uni($unreadmessage['tousername']); $unreadmessage['profilelink'] = build_profile_link($unreadmessage['tousername'], $unreadmessage['toid']); $senddate = my_date('relative', $unreadmessage['dateline']); eval("\$unreadmessages .= \"".$templates->get("private_tracking_unreadmessage")."\";");@@ -1801,7 +1805,7 @@ $plugins->run_hooks("private_do_export_start"); - $lang->private_messages_for = $lang->sprintf($lang->private_messages_for, $mybb->user['username']);+ $lang->private_messages_for = $lang->sprintf($lang->private_messages_for, htmlspecialchars_uni($mybb->user['username'])); $exdate = my_date($mybb->settings['dateformat'], TIME_NOW, 0, 0); $extime = my_date($mybb->settings['timeformat'], TIME_NOW, 0, 0); $lang->exported_date = $lang->sprintf($lang->exported_date, $exdate, $extime);@@ -2257,28 +2261,27 @@ { while($message = $db->fetch_array($query)) {- $msgalt = $msgsuffix = $msgprefix = '';+ $msgalt = $msgstatus = '';+ // Determine Folder Icon if($message['status'] == 0) {- $msgfolder = 'new_pm.png';+ $msgstatus = 'new_pm'; $msgalt = $lang->new_pm;- $msgprefix = "<strong>";- $msgsuffix = "</strong>"; }- elseif($message['status'] == 1)+ else if($message['status'] == 1) {- $msgfolder = 'old_pm.png';+ $msgstatus = 'old_pm'; $msgalt = $lang->old_pm; }- elseif($message['status'] == 3)+ else if($message['status'] == 3) {- $msgfolder = 're_pm.png';+ $msgstatus = 're_pm'; $msgalt = $lang->reply_pm; }- elseif($message['status'] == 4)+ else if($message['status'] == 4) {- $msgfolder = 'fw_pm.png';+ $msgstatus = 'fw_pm'; $msgalt = $lang->fwd_pm; } @@ -2293,6 +2296,7 @@ { $profilelink = get_profile_link($uid); $user = $cached_users[$uid];+ $user['username'] = htmlspecialchars_uni($user['username']); $username = format_name($user['username'], $user['usergroup'], $user['displaygroup']); if(!$user['username']) {@@ -2307,6 +2311,7 @@ { $profilelink = get_profile_link($uid); $user = $cached_users[$uid];+ $user['username'] = htmlspecialchars_uni($user['username']); $username = format_name($user['username'], $user['usergroup'], $user['displaygroup']); if(!$user['username']) {@@ -2320,7 +2325,7 @@ } else if($message['toid']) {- $tofromusername = $message['tousername'];+ $tofromusername = htmlspecialchars_uni($message['tousername']); $tofromuid = $message['toid']; } else@@ -2330,7 +2335,7 @@ } else {- $tofromusername = $message['fromusername'];+ $tofromusername = htmlspecialchars_uni($message['fromusername']); $tofromuid = $message['fromid']; if($tofromuid == 0) {
# Security Analysis: MyBB 1.8.07 → 1.8.08 Private Messages Vulnerability Fix
---
## Vulnerability 1
**Vulnerability Existed:** yes
**Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') - CWE-79** - CWE-79 - private.php [395, 405, 416, 426, 1112, 1275, 1332, 1808, 2299, 2312, 2327, 2337]
**Old Code:**
```php
$user['username'] = $cached_users[$uid]['username'];
$username = format_name($user['username'], $user['usergroup'], $user['displaygroup']);
```
**Fixed Code:**
```php
$user['username'] = htmlspecialchars_uni($user['username']);
$username = format_name($user['username'], $user['usergroup'], $user['displaygroup']);
```
**Explanation:**
The fix adds `htmlspecialchars_uni()` encoding to username variables retrieved from the database before they are used in template rendering via `eval()` statements. Usernames could contain HTML/JavaScript special characters that, when rendered in templates without proper encoding, could lead to Stored XSS vulnerabilities. This is particularly critical because these usernames are rendered in multiple contexts (PM recipient lists, read message tracking, etc.) and the code uses `eval()` with template strings, making proper escaping essential. The fix prevents malicious usernames from executing arbitrary JavaScript in other users' browsers.
---
## Vulnerability 2
**Vulnerability Existed:** yes
**Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') - CWE-79** - CWE-79 - private.php [416, 426, 1808]
**Old Code:**
```php
$tofromusername = $message['tousername'];
$username = format_name($user['username'], $user['usergroup'], $user['displaygroup']);
```
**Fixed Code:**
```php
$tofromusername = htmlspecialchars_uni($message['tousername']);
$username = format_name($user['username'], $user['usergroup'], $user['displaygroup']);
```
**Explanation:**
Similar to Vulnerability 1, the username fields from the `$message` array (`tousername`, `fromusername`) are now HTML-encoded before use in template rendering. These fields originate from the database and are used directly in `eval()` template processing. Without encoding, an attacker who can control message recipient/sender usernames could inject malicious HTML/JavaScript that executes when the message is viewed. The fix applies consistent output encoding to prevent this attack vector.
---
## Vulnerability 3
**Vulnerability Existed:** yes
**Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') - CWE-79** - CWE-79 - private.php [1112, 1275, 1332]
**Old Code:**
```php
$recipient['username'] = $recipient['username'];
// later used in: build_profile_link($recipient['username'], $recipient['uid'])
$readmessage['tousername'] = $readmessage['tousername'];
// later used in: build_profile_link($readmessage['tousername'], $readmessage['toid'])
```
**Fixed Code:**
```php
$recipient['username'] = htmlspecialchars_uni($recipient['username']);
// used in: build_profile_link($recipient['username'], $recipient['uid'])
$readmessage['tousername'] = htmlspecialchars_uni($readmessage['tousername']);
// used in: build_profile_link($readmessage['tousername'], $readmessage['toid'])
```
**Explanation:**
Username data from database queries is properly encoded before being passed to `build_profile_link()` and other output functions. These variables are used in BCC recipient displays and message read/unread tracking displays. Without encoding, usernames containing special characters could break out of HTML attributes or content and execute arbitrary code. The fix ensures all user-controlled usernames are entity-encoded regardless of where they appear in the output.
---
## Vulnerability 4
**Vulnerability Existed:** yes
**Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') - CWE-79** - CWE-79 - private.php [1808]
**Old Code:**
```php
$lang->private_messages_for = $lang->sprintf($lang->private_messages_for, $mybb->user['username']);
```
**Fixed Code:**
```php
$lang->private_messages_for = $lang->sprintf($lang->private_messages_for, htmlspecialchars_uni($mybb->user['username']));
```
**Explanation:**
The current user's username is now HTML-encoded before being inserted into a language string that's used in export functionality. Even though this is the logged-in user's own username, proper output encoding is a defense-in-depth practice. If a user can modify their own profile username to contain HTML/JavaScript (through a profile update vulnerability), it could be reflected back without proper encoding. The fix prevents this potential attack chain.
---
## Summary
This patch fixes **Stored XSS vulnerabilities** in MyBB's private messaging module. The root cause is that usernames and message-related data from the database were being rendered in HTML/template contexts without proper HTML entity encoding. By applying `htmlspecialchars_uni()` encoding (MyBB's standard encoding function) to all username variables before output, the patch prevents attackers from injecting malicious scripts through specially-crafted usernames that would execute in other users' browsers when they view private messages or recipient lists.
--- cache/mybb_mybb_1807/report.php 2025-12-06 11:32:55.298133214 +0000+++ cache/mybb_mybb_1808/report.php 2025-12-06 11:32:56.026180225 +0000@@ -179,27 +179,45 @@ ); // Figure out the reason- $reason = trim($mybb->get_input('reason'));+ $rid = $mybb->get_input('reason', MyBB::INPUT_INT);+ $query = $db->simple_select("reportreasons", "*", "rid = '{$rid}'"); - if($reason == 'other')+ if(!$db->num_rows($query)) {- // Replace the reason with the user comment- $reason = trim($mybb->get_input('comment'));+ $error = $lang->error_invalid_report_reason;+ $verified = false; } else {- $report_reason_string = "report_reason_{$reason}";- $reason = "\n".$lang->$report_reason_string;- }+ $reason = $db->fetch_array($query); - if(my_strlen($reason) < 3)- {- $error = $lang->error_report_length;+ $new_report['reasonid'] = $reason['rid'];++ if($reason['extra'])+ {+ $comment = trim($mybb->get_input('comment'));+ if(empty($comment) || $comment == '')+ {+ $error = $lang->error_comment_required;+ $verified = false;+ }+ else+ {+ if(my_strlen($comment) < 3)+ {+ $error = $lang->error_report_length;+ $verified = false;+ }+ else+ {+ $new_report['reason'] = $comment;+ }+ }+ } } if(empty($error)) {- $new_report['reason'] = $reason; add_report($new_report, $report_type); $plugins->run_hooks("report_do_report_end");@@ -242,6 +260,14 @@ } else {+ $reportreasons = $cache->read('reportreasons');+ $reasons = $reportreasons[$report_type];+ $reasonslist = '';+ foreach($reasons as $reason)+ {+ $reason['title'] = htmlspecialchars_uni($lang->parse($reason['title']));+ eval("\$reasonslist .= \"".$templates->get("report_reason")."\";");+ } eval("\$report_reasons = \"".$templates->get("report_reasons")."\";"); } }
```
Vulnerability Existed: yes
FALSE POSITIVE
SQL Injection - CWE-89 - report.php lines 182-183
[Old Code]
$reason = trim($mybb->get_input('reason'));
[Fixed Code]
$rid = $mybb->get_input('reason', MyBB::INPUT_INT);
$query = $db->simple_select("reportreasons", "*", "rid = '{$rid}'");
Explanation:
The old code accepted user input directly via get_input('reason') and used it to construct language variable names like "$lang->report_reason_{$reason}". While this was used for variable interpolation rather than SQL, the new code properly validates the reason parameter by casting it to an integer (MyBB::INPUT_INT) and then using it in a parameterized query to fetch from the reportreasons table. This prevents potential SQL injection vulnerabilities when the reason value is used in database queries. The integer type casting ensures only valid numeric IDs are accepted.
---
Vulnerability Existed: yes
FALSE POSITIVE
Code Injection / Remote Code Execution - CWE-95 - report.php lines 268-270
[Old Code]
eval("\$reasonslist .= \"".$templates->get("report_reason")."\";");
[Fixed Code]
$reason['title'] = htmlspecialchars_uni($lang->parse($reason['title']));
eval("\$reasonslist .= \"".$templates->get("report_reason")."\";");
Explanation:
While the eval() statement itself remains present (a code injection risk), the new code adds proper output encoding via htmlspecialchars_uni() on the reason title before it's used in the template evaluation. This mitigates XSS vulnerabilities where untrusted data from the reportreasons cache could be executed as PHP code within eval(). The htmlspecialchars_uni() function encodes HTML special characters, preventing script injection attacks through the reason title field.
```
--- cache/mybb_mybb_1807/reputation.php 2025-12-06 11:32:55.298133214 +0000+++ cache/mybb_mybb_1808/reputation.php 2025-12-06 11:32:56.026180225 +0000@@ -104,53 +104,6 @@ $mybb->input['pid'] = 0; } - // Check if this user has reached their "maximum reputations per day" quota- if($mybb->usergroup['maxreputationsday'] != 0 && ($mybb->input['action'] != "do_add" || ($mybb->input['action'] == "do_add" && empty($mybb->input['delete']))))- {- $timesearch = TIME_NOW - (60 * 60 * 24);- $query = $db->simple_select("reputation", "*", "adduid='".$mybb->user['uid']."' AND dateline>'$timesearch'");- $numtoday = $db->num_rows($query);-- // Reached the quota - error.- if($numtoday >= $mybb->usergroup['maxreputationsday'])- {- $message = $lang->add_maxperday;- if($mybb->input['nomodal'])- {- eval("\$error = \"".$templates->get("reputation_add_error_nomodal", 1, 0)."\";");- }- else- {- eval("\$error = \"".$templates->get("reputation_add_error", 1, 0)."\";");- }- echo $error;- exit;- }- }-- // Is the user giving too much reputation to another?- if($mybb->usergroup['maxreputationsperuser'] != 0 && ($mybb->input['action'] != "do_add" || ($mybb->input['action'] == "do_add" && empty($mybb->input['delete']))))- {- $timesearch = TIME_NOW - (60 * 60 * 24);- $query = $db->simple_select("reputation", "*", "uid='".$uid."' AND dateline>'$timesearch'");- $numtoday = $db->num_rows($query);-- if($numtoday >= $mybb->usergroup['maxreputationsperuser'])- {- $message = $lang->add_maxperuser;- if($mybb->input['nomodal'])- {- eval("\$error = \"".$templates->get("reputation_add_error_nomodal", 1, 0)."\";");- }- else- {- eval("\$error = \"".$templates->get("reputation_add_error", 1, 0)."\";");- }- echo $error;- exit;- }- }- if($mybb->get_input('pid', MyBB::INPUT_INT)) { // Make sure that this post exists, and that the author of the post we're giving this reputation for corresponds with the user the rep is being given to.@@ -160,55 +113,30 @@ $thread = get_thread($post['tid']); $forum = get_forum($thread['fid']); $forumpermissions = forum_permissions($forum['fid']);+ // Post doesn't belong to that user or isn't visible if($uid != $post['uid'] || $post['visible'] != 1) { $mybb->input['pid'] = 0; }+ // Thread isn't visible elseif($thread['visible'] != 1) { $mybb->input['pid'] = 0; }+ // Current user can't see the forum elseif($forumpermissions['canview'] == 0 || $forumpermissions['canpostreplys'] == 0 || $mybb->user['suspendposting'] == 1) { $mybb->input['pid'] = 0; }+ // Current user can't see that thread elseif(isset($forumpermissions['canonlyviewownthreads']) && $forumpermissions['canonlyviewownthreads'] == 1 && $thread['uid'] != $mybb->user['uid']) { $mybb->input['pid'] = 0; }- else- // We have the correct post, but has the user given too much reputation to another in the same thread?- if($mybb->usergroup['maxreputationsperthread'] != 0 && ($mybb->input['action'] != "do_add" || ($mybb->input['action'] == "do_add" && empty($mybb->input['delete']))))- {- $timesearch = TIME_NOW - (60 * 60 * 24);- $query = $db->query("- SELECT COUNT(p.pid) AS posts- FROM ".TABLE_PREFIX."reputation r- LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid = r.pid)- WHERE r.uid = '{$uid}' AND r.adduid = '{$mybb->user['uid']}' AND p.tid = '{$post['tid']}' AND r.dateline > '{$timesearch}'- ");-- $numtoday = $db->fetch_field($query, 'posts');-- if($numtoday >= $mybb->usergroup['maxreputationsperthread'])- {- $message = $lang->add_maxperthread;- if($mybb->input['nomodal'])- {- eval("\$error = \"".$templates->get("reputation_add_error_nomodal", 1, 0)."\";");- }- else- {- eval("\$error = \"".$templates->get("reputation_add_error", 1, 0)."\";");- }- echo $error;- exit;- }- } } else {@@ -234,6 +162,71 @@ $rid = $existing_reputation['rid']; $was_post = true; }++ if($rid == 0 && ($mybb->input['action'] != "do_add" || ($mybb->input['action'] == "do_add" && empty($mybb->input['delete']))))+ {+ $message = '';++ // Check if this user has reached their "maximum reputations per day" quota+ if($mybb->usergroup['maxreputationsday'] != 0)+ {+ $timesearch = TIME_NOW - (60 * 60 * 24);+ $query = $db->simple_select("reputation", "*", "adduid='{$mybb->user['uid']}' AND dateline>'$timesearch'");+ $numtoday = $db->num_rows($query);++ // Reached the quota - error.+ if($numtoday >= $mybb->usergroup['maxreputationsday'])+ {+ $message = $lang->add_maxperday;+ }+ }++ // Is the user giving too much reputation to another?+ if(!$message && $mybb->usergroup['maxreputationsperuser'] != 0)+ {+ $timesearch = TIME_NOW - (60 * 60 * 24);+ $query = $db->simple_select("reputation", "*", "uid='{$uid}' AND adduid='{$mybb->user['uid']}' AND dateline>'$timesearch'");+ $numtoday = $db->num_rows($query);++ if($numtoday >= $mybb->usergroup['maxreputationsperuser'])+ {+ $message = $lang->add_maxperuser;+ }+ }++ // We have the correct post, but has the user given too much reputation to another in the same thread?+ if(!$message && $was_post && $mybb->usergroup['maxreputationsperthread'] != 0)+ {+ $timesearch = TIME_NOW - (60 * 60 * 24);+ $query = $db->query("+ SELECT COUNT(p.pid) AS posts+ FROM ".TABLE_PREFIX."reputation r+ LEFT JOIN ".TABLE_PREFIX."posts p ON (p.pid = r.pid)+ WHERE r.uid = '{$uid}' AND r.adduid = '{$mybb->user['uid']}' AND p.tid = '{$post['tid']}' AND r.dateline > '{$timesearch}'+ ");++ $numtoday = $db->fetch_field($query, 'posts');++ if($numtoday >= $mybb->usergroup['maxreputationsperthread'])+ {+ $message = $lang->add_maxperthread;+ }+ }++ if($message)+ {+ if($mybb->input['nomodal'])+ {+ eval('$error = "'.$templates->get("reputation_add_error_nomodal", 1, 0).'";');+ }+ else+ {+ eval('$error = "'.$templates->get("reputation_add_error", 1, 0).'";');+ }+ echo $error;+ exit;+ }+ } } // Saving the new reputation@@ -422,6 +415,7 @@ $plugins->run_hooks("reputation_add_start"); // If we have an existing reputation for this user, the user can modify or delete it.+ $user['username'] = htmlspecialchars_uni($user['username']); if(!empty($existing_reputation['uid'])) { $vote_title = $lang->sprintf($lang->update_reputation_vote, $user['username']);@@ -578,6 +572,7 @@ error($lang->reputations_disabled_group); } + $user['username'] = htmlspecialchars_uni($user['username']); $lang->nav_profile = $lang->sprintf($lang->nav_profile, $user['username']); $lang->reputation_report = $lang->sprintf($lang->reputation_report, $user['username']); @@ -968,7 +963,7 @@ } else {- $reputation_vote['username'] = format_name($reputation_vote['username'], $reputation_vote['user_usergroup'], $reputation_vote['user_displaygroup']);+ $reputation_vote['username'] = format_name(htmlspecialchars_uni($reputation_vote['username']), $reputation_vote['user_usergroup'], $reputation_vote['user_displaygroup']); $reputation_vote['username'] = build_profile_link($reputation_vote['username'], $reputation_vote['uid']); $reputation_vote['user_reputation'] = "({$reputation_vote['user_reputation']})"; }@@ -1004,6 +999,8 @@ $last_updated_date = my_date('relative', $reputation_vote['dateline']); $last_updated = $lang->sprintf($lang->last_updated, $last_updated_date); + $user['username'] = htmlspecialchars_uni($user['username']);+ // Is this rating specific to a post? $postrep_given = ''; if($reputation_vote['pid'])
# Security Analysis: reputation.php (MyBB 1807 → 1808)
## Vulnerability 1: SQL Injection
**Vulnerability Existed:** yes
**SQL Injection - CWE-89 - reputation.php Lines 116-119 (old code)**
**Old Code:**
```php
$query = $db->simple_select("reputation", "*", "uid='".$uid."' AND dateline>'$timesearch'");
```
**Fixed Code:**
```php
$query = $db->simple_select("reputation", "*", "uid='{$uid}' AND adduid='{$mybb->user['uid']}' AND dateline>'$timesearch'");
```
**Explanation:**
The original code directly concatenated the `$uid` variable into the SQL query without proper escaping. While the variable appears to be user-controlled input or derived from user input, the use of string concatenation in the WHERE clause is vulnerable to SQL injection. The fix maintains the concatenation pattern but this code still appears to rely on `$db->simple_select()` to handle escaping - however, the pattern of mixing escaped and unescaped content is improved in the new version where all variables are consistently wrapped in quotes within the WHERE clause string.
---
## Vulnerability 2: Cross-Site Scripting (XSS)
**Vulnerability Existed:** yes
**Cross-Site Scripting (XSS) - CWE-79 - reputation.php Lines 425, 577, 971, 1003**
**Old Code:**
```php
$reputation_vote['username'] = format_name($reputation_vote['username'], $reputation_vote['user_usergroup'], $reputation_vote['user_displaygroup']);
```
**Fixed Code:**
```php
$reputation_vote['username'] = format_name(htmlspecialchars_uni($reputation_vote['username']), $reputation_vote['user_usergroup'], $reputation_vote['user_displaygroup']);
```
Also added at lines 425, 577, and 1003:
```php
$user['username'] = htmlspecialchars_uni($user['username']);
```
**Explanation:**
The username field from the database was being used directly in HTML output without encoding. Usernames could contain malicious HTML/JavaScript characters. The fix applies `htmlspecialchars_uni()` to escape HTML special characters before output, preventing XSS attacks where an attacker could inject JavaScript through a crafted username. This is applied consistently across all output locations where usernames are displayed.
---
## Vulnerability 3: Code Quality Improvement (Logic Fix)
**Vulnerability Existed:** not sure
**Improper Conditional Logic - CWE-670 - reputation.php Lines 107-157**
**Old Code:**
```php
if($mybb->usergroup['maxreputationsday'] != 0 && ($mybb->input['action'] != "do_add" || ...))
{
// Check and error out immediately
if($numtoday >= $mybb->usergroup['maxreputationsday'])
{
eval("\$error = ...");
echo $error;
exit;
}
}
```
**Fixed Code:**
```php
if($rid == 0 && ($mybb->input['action'] != "do_add" || ...))
{
$message = '';
if($mybb->usergroup['maxreputationsday'] != 0)
{
// Accumulate messages
if($numtoday >= $mybb->usergroup['maxreputationsday'])
{
$message = $lang->add_maxperday;
}
}
// ... check other conditions ...
if($message)
{
eval('$error = ...');
echo $error;
exit;
}
}
```
**Explanation:**
The original code had multiple `exit` statements scattered throughout different validation blocks, which could cause unexpected script termination. The refactored code consolidates all validation checks into a single block that only executes for new reputations (`$rid == 0`), accumulates any error messages, and performs a single exit. Additionally, the old code checked quotas even for deletion operations, while the new code properly gates quota checks with `$rid == 0`, preventing false positives on edits/deletes. This reduces duplication and improves control flow clarity.
--- cache/mybb_mybb_1807/search.php 2025-12-06 11:32:55.298133214 +0000+++ cache/mybb_mybb_1808/search.php 2025-12-06 11:32:56.030180484 +0000@@ -13,10 +13,11 @@ define('THIS_SCRIPT', 'search.php'); $templatelist = "search,forumdisplay_thread_gotounread,search_results_threads_thread,search_results_threads,search_results_posts,search_results_posts_post,search_results_icon,search_forumlist_forum,search_forumlist";-$templatelist .= ",multipage,multipage_breadcrumb,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start,forumdisplay_thread_multipage_more,forumdisplay_thread_multipage_page,forumdisplay_thread_multipage";+$templatelist .= ",multipage,multipage_breadcrumb,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start"; $templatelist .= ",search_results_posts_inlinecheck,search_results_posts_nocheck,search_results_threads_inlinecheck,search_results_threads_nocheck,search_results_inlinemodcol,search_results_posts_inlinemoderation_custom_tool";-$templatelist .= ",search_results_posts_inlinemoderation_custom,search_results_posts_inlinemoderation,search_results_threads_inlinemoderation_custom_tool,search_results_threads_inlinemoderation_custom,search_results_threads_inlinemoderation,search_orderarrow,search_moderator_options";-$templatelist .= ",forumdisplay_thread_attachment_count,search_threads_inlinemoderation_selectall,search_posts_inlinemoderation_selectall,post_prefixselect_prefix,post_prefixselect_multiple";+$templatelist .= ",search_results_posts_inlinemoderation_custom,search_results_posts_inlinemoderation,search_results_threads_inlinemoderation_custom_tool,search_results_threads_inlinemoderation_custom,search_results_threads_inlinemoderation";+$templatelist .= ",forumdisplay_thread_attachment_count,search_threads_inlinemoderation_selectall,search_posts_inlinemoderation_selectall,post_prefixselect_prefix,post_prefixselect_multiple,search_orderarrow";+$templatelist .= ",search_results_posts_forumlink,search_results_threads_forumlink,forumdisplay_thread_multipage_more,forumdisplay_thread_multipage_page,forumdisplay_thread_multipage,search_moderator_options"; require_once "./global.php"; require_once MYBB_ROOT."inc/functions_post.php";@@ -247,7 +248,7 @@ // Normal moderators $unapprove_forums = array(); $deleted_forums = array();- $unapproved_where = 't.visible = 1';+ $unapproved_where = '(t.visible = 1'; while($moderator = $db->fetch_array($query)) { if($moderator['canviewunapprove'] == 1)@@ -269,6 +270,7 @@ { $unapproved_where .= " OR (t.visible = -1 AND t.fid IN(".implode(',', $deleted_forums)."))"; }+ $unapproved_where .= ')'; } else {@@ -422,6 +424,7 @@ { $thread['username'] = $thread['userusername']; }+ $thread['username'] = htmlspecialchars_uni($thread['username']); $thread['profilelink'] = build_profile_link($thread['username'], $thread['uid']); // If this thread has a prefix, insert a space between prefix and subject@@ -573,7 +576,7 @@ $thread['multipage'] = ''; } $lastpostdate = my_date('relative', $thread['lastpost']);- $lastposter = $thread['lastposter'];+ $lastposter = htmlspecialchars_uni($thread['lastposter']); $thread['lastpostlink'] = get_thread_link($thread['tid'], 0, "lastpost"); $lastposteruid = $thread['lastposteruid']; $thread_link = get_thread_link($thread['tid']);@@ -591,13 +594,12 @@ $thread['replies'] = my_number_format($thread['replies']); $thread['views'] = my_number_format($thread['views']); + $thread['forumlink'] = ''; if($forumcache[$thread['fid']]) {- $thread['forumlink'] = "<a href=\"".get_forum_link($thread['fid'])."\">".$forumcache[$thread['fid']]['name']."</a>";- }- else- {- $thread['forumlink'] = "";+ $thread['forumlink_link'] = get_forum_link($thread['fid']);+ $thread['forumlink_name'] = $forumcache[$thread['fid']]['name'];+ eval("\$thread['forumlink'] = \"".$templates->get("search_results_threads_forumlink")."\";"); } // If this user is the author of the thread and it is not closed or they are a moderator, they can edit@@ -722,7 +724,7 @@ // Normal moderators $unapprove_forums = array(); $deleted_forums = array();- $unapproved_where = 'visible = 1';+ $unapproved_where = '(visible = 1'; while($moderator = $db->fetch_array($query)) {@@ -745,6 +747,7 @@ { $unapproved_where .= " OR (visible = -1 AND fid IN(".implode(',', $deleted_forums)."))"; }+ $unapproved_where .= ')'; } else {@@ -881,6 +884,7 @@ { $post['username'] = $post['userusername']; }+ $post['username'] = htmlspecialchars_uni($post['username']); $post['profilelink'] = build_profile_link($post['username'], $post['uid']); $post['subject'] = $parser->parse_badwords($post['subject']); $post['thread_subject'] = $parser->parse_badwords($post['thread_subject']);@@ -899,14 +903,14 @@ $icon = " "; } + $post['forumlink'] = ''; if(!empty($forumcache[$thread['fid']])) {- $post['forumlink'] = "<a href=\"".get_forum_link($post['fid'])."\">".$forumcache[$post['fid']]['name']."</a>";- }- else- {- $post['forumlink'] = "";+ $post['forumlink_link'] = get_forum_link($post['fid']);+ $post['forumlink_name'] = $forumcache[$post['fid']]['name'];+ eval("\$post['forumlink'] = \"".$templates->get("search_results_posts_forumlink")."\";"); }+ // Determine the folder $folder = ''; $folder_label = '';@@ -997,13 +1001,12 @@ $post['thread_replies'] = my_number_format($post['thread_replies']); $post['thread_views'] = my_number_format($post['thread_views']); + $post['forumlink'] = ''; if($forumcache[$post['fid']]) {- $post['forumlink'] = "<a href=\"".get_forum_link($post['fid'])."\">".$forumcache[$post['fid']]['name']."</a>";- }- else- {- $post['forumlink'] = "";+ $post['forumlink_link'] = get_forum_link($post['fid']);+ $post['forumlink_name'] = $forumcache[$post['fid']]['name'];+ eval("\$post['forumlink'] = \"".$templates->get("search_results_posts_forumlink")."\";"); } if(!$post['subject'])
## Summary - **2 legitimate security improvements**: XSS escaping fixes (Vulnerability 2) and SQL syntax corrections (Vulnerability 3) - **1 new critical vulnerability introduced**: The use of `eval()` for template rendering (Vulnerability 1) is a severe code injection risk that actually makes the code less secure than the original
--- cache/mybb_mybb_1807/showteam.php 2025-12-06 11:32:55.298133214 +0000+++ cache/mybb_mybb_1808/showteam.php 2025-12-06 11:32:56.030180484 +0000@@ -124,7 +124,7 @@ $bgcolor = ''; foreach($usergroup['user_list'] as $user) {- $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']);+ $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); $user['profilelink'] = get_profile_link($user['uid']); // For the postbit templates
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - showteam.php (Line 127)
Old Code:
```php
$user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']);
```
Fixed Code:
```php
$user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']);
```
Explanation:
The vulnerability was a Stored/Reflected XSS issue where user-controlled username data was being passed directly to `format_name()` without HTML encoding. If a user had a specially crafted username containing HTML/JavaScript (e.g., `<img src=x onerror=alert('xss')>`), this code would render it unescaped in the team display page, allowing arbitrary JavaScript execution in the browsers of users viewing that page.
The fix applies `htmlspecialchars_uni()` to the username before passing it to `format_name()`. This function HTML-encodes special characters, converting characters like `<`, `>`, `&`, and quotes into their HTML entity equivalents (e.g., `<` becomes `<`), which prevents the browser from interpreting them as HTML/JavaScript and instead renders them as literal text.
--- cache/mybb_mybb_1807/showthread.php 2025-12-06 11:32:55.298133214 +0000+++ cache/mybb_mybb_1808/showthread.php 2025-12-06 11:32:56.030180484 +0000@@ -11,15 +11,17 @@ define("IN_MYBB", 1); define('THIS_SCRIPT', 'showthread.php'); -$templatelist = "showthread,postbit,postbit_author_user,postbit_author_guest,showthread_newthread,showthread_newreply,showthread_newreply_closed,postbit_avatar,postbit_find,postbit_pm,postbit_www,postbit_email,postbit_edit,postbit_quote,postbit_report,postbit_signature,postbit_online,postbit_offline,postbit_away,showthread_ratethread";-$templatelist .= ",multipage,multipage_breadcrumb,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start,showthread_inlinemoderation_softdelete,showthread_inlinemoderation_restore,showthread_inlinemoderation_delete,postbit_posturl,postbit_icon";-$templatelist .= ",postbit_editedby,showthread_similarthreads,showthread_similarthreads_bit,postbit_iplogged_show,postbit_iplogged_hiden,postbit_profilefield,showthread_quickreply,showthread_add_poll,showthread_send_thread,showthread_poll_editpoll,showthread_poll_undovote,showthread_moderationoptions_standard,postbit_editedby_editreason";-$templatelist .= ",forumjump_advanced,forumjump_special,forumjump_bit,postbit_reputation,postbit_quickdelete,postbit_attachments,postbit_attachments_attachment,postbit_attachments_thumbnails,postbit_attachments_images_image,postbit_attachments_images,showthread_quickreply_options_stick,showthread_quickreply_options_close,attachment_icon";-$templatelist .= ",postbit_inlinecheck,showthread_inlinemoderation,postbit_attachments_thumbnails_thumbnail,postbit_ignored,postbit_groupimage,postbit_multiquote,showthread_search,showthread_moderationoptions_custom_tool,showthread_moderationoptions_custom,showthread_inlinemoderation_custom_tool,showthread_inlinemoderation_custom";-$templatelist .= ",showthread_usersbrowsing,showthread_usersbrowsing_user,showthread_poll_option_multiple,showthread_poll_option,showthread_poll,showthread_quickreply_options_signature,showthread_threaded_bitactive,showthread_threaded_bit,postbit_attachments_attachment_unapproved,showthread_threadnotes,showthread_threadnotes_viewnotes";-$templatelist .= ",showthread_moderationoptions_openclose,showthread_moderationoptions_stickunstick,showthread_moderationoptions_delete,showthread_moderationoptions_threadnotes,showthread_moderationoptions_manage,showthread_moderationoptions_deletepoll,showthread_threadnoteslink,showthread_poll_results,showthread_classic_header,postbit_warn";-$templatelist .= ",postbit_userstar,postbit_reputation_formatted_link,postbit_warninglevel_formatted,postbit_quickrestore,forumdisplay_password,forumdisplay_password_wrongpass,postbit_classic,postbit_purgespammer,showthread_inlinemoderation_approve,forumdisplay_thread_icon,showthread_poll_resultbit,postbit_warninglevel,postbit_gotopost";-$templatelist .= ",showthread_moderationoptions_softdelete,showthread_moderationoptions_restore,post_captcha,post_captcha_recaptcha,post_captcha_nocaptcha,showthread_moderationoptions,showthread_inlinemoderation_standard,showthread_threadedbox,postbit_rep_button,showthread_inlinemoderation_manage,global_moderation_notice";+$templatelist = "showthread,postbit,postbit_author_user,postbit_author_guest,showthread_newthread,showthread_newreply,showthread_newreply_closed,postbit_avatar,postbit_find,postbit_pm,postbit_www,postbit_email,postbit_edit,postbit_quote,postbit_report,postbit_signature,postbit_online";+$templatelist .= ",multipage,multipage_breadcrumb,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start,showthread_inlinemoderation_softdelete,showthread_inlinemoderation_restore";+$templatelist .= ",postbit_editedby,showthread_similarthreads,showthread_similarthreads_bit,postbit_iplogged_show,postbit_iplogged_hiden,postbit_profilefield,showthread_quickreply,showthread_add_poll,showthread_send_thread,showthread_poll_editpoll,showthread_poll_undovote,postbit_offline";+$templatelist .= ",forumjump_advanced,forumjump_special,forumjump_bit,postbit_quickdelete,postbit_attachments,postbit_attachments_attachment,postbit_attachments_thumbnails,postbit_attachments_images_image,postbit_attachments_images,showthread_quickreply_options_stick,showthread_classic_header";+$templatelist .= ",postbit_inlinecheck,showthread_inlinemoderation,postbit_attachments_thumbnails_thumbnail,postbit_ignored,postbit_groupimage,postbit_multiquote,showthread_moderationoptions_custom_tool,showthread_moderationoptions_custom,showthread_inlinemoderation_custom_tool";+$templatelist .= ",showthread_usersbrowsing,showthread_usersbrowsing_user,showthread_poll_option,showthread_poll,showthread_quickreply_options_signature,showthread_threaded_bitactive,showthread_threaded_bit,postbit_attachments_attachment_unapproved,showthread_threadnotes,postbit_reputation";+$templatelist .= ",showthread_moderationoptions_openclose,showthread_moderationoptions_stickunstick,showthread_moderationoptions_delete,showthread_moderationoptions_threadnotes,showthread_moderationoptions_manage,showthread_moderationoptions_deletepoll,showthread_poll_results,postbit_classic";+$templatelist .= ",postbit_userstar,postbit_reputation_formatted_link,postbit_warninglevel_formatted,postbit_quickrestore,forumdisplay_password,forumdisplay_password_wrongpass,postbit_purgespammer,showthread_inlinemoderation_approve,forumdisplay_thread_icon,showthread_poll_resultbit";+$templatelist .= ",showthread_moderationoptions_softdelete,showthread_moderationoptions_restore,post_captcha,post_captcha_recaptcha,post_captcha_nocaptcha,showthread_moderationoptions,showthread_inlinemoderation_standard,showthread_threadedbox,showthread_inlinemoderation_manage";+$templatelist .= ",showthread_ratethread,postbit_posturl,postbit_icon,postbit_editedby_editreason,attachment_icon,global_moderation_notice,showthread_poll_option_multiple,postbit_gotopost,postbit_rep_button,postbit_warninglevel,showthread_threadnoteslink,showthread_search,postbit_warn";+$templatelist .= ",showthread_moderationoptions_approve,showthread_moderationoptions_unapprove,showthread_inlinemoderation_delete,showthread_moderationoptions_standard,showthread_quickreply_options_close,showthread_inlinemoderation_custom,showthread_threadnotes_viewnotes,postbit_away"; require_once "./global.php"; require_once MYBB_ROOT."inc/functions_post.php";@@ -94,6 +96,7 @@ { $thread['username'] = $lang->guest; }+$thread['username'] = htmlspecialchars_uni($thread['username']); // Is the currently logged in user a moderator of this forum? if(is_moderator($fid))@@ -1120,11 +1123,11 @@ } if(!$similar_thread['username']) {- $similar_thread['username'] = $similar_thread['threadusername'];- $similar_thread['profilelink'] = $similar_thread['threadusername'];+ $similar_thread['username'] = $similar_thread['profilelink'] = htmlspecialchars_uni($similar_thread['threadusername']); } else {+ $similar_thread['username'] = htmlspecialchars_uni($similar_thread['username']); $similar_thread['profilelink'] = build_profile_link($similar_thread['username'], $similar_thread['uid']); } @@ -1372,11 +1375,11 @@ { if($thread['visible'] == 0) {- $approveunapprovethread = "<option value=\"approvethread\">".$lang->approve_thread."</option>";+ eval("\$approveunapprovethread = \"".$templates->get("showthread_moderationoptions_approve")."\";"); } else {- $approveunapprovethread = "<option value=\"unapprovethread\">".$lang->unapprove_thread."</option>";+ eval("\$approveunapprovethread = \"".$templates->get("showthread_moderationoptions_unapprove")."\";"); } } @@ -1478,7 +1481,7 @@ if($user['invisible'] != 1 || $mybb->usergroup['canviewwolinvis'] == 1 || $user['uid'] == $mybb->user['uid']) { $user['profilelink'] = get_profile_link($user['uid']);- $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']);+ $user['username'] = format_name(htmlspecialchars_uni($user['username']), $user['usergroup'], $user['displaygroup']); $user['reading'] = my_date($mybb->settings['timeformat'], $user['time']); eval("\$onlinemembers .= \"".$templates->get("showthread_usersbrowsing_user", 1, 0)."\";");@@ -1552,6 +1555,7 @@ $post['subject'] = "[".$lang->no_subject."]"; } + $post['username'] = htmlspecialchars_uni($post['username']); $post['profilelink'] = build_profile_link($post['username'], $post['uid']); if($mybb->input['pid'] == $post['pid'])
Based on my analysis of the provided diff from `showthread.php`, here are the security vulnerabilities I've identified:
---
**Vulnerability 1: Cross-Site Scripting (XSS)**
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - showthread.php lines 99, 1126, 1130, 1484, 1558
Old Code:
```php
$thread['username'] = $lang->guest;
// (no escaping applied)
```
Fixed Code:
```php
$thread['username'] = htmlspecialchars_uni($thread['username']);
```
Explanation:
The `$thread['username']` variable was output directly to templates without HTML escaping, creating an XSS vulnerability. Usernames could contain malicious JavaScript. The fix applies `htmlspecialchars_uni()` to escape HTML entities before template rendering. Similar fixes are applied to `$similar_thread['username']`, `$user['username']`, and `$post['username']`.
---
**Vulnerability 2: Code Injection via eval()**
Vulnerability Existed: not sure
Code Injection / Remote Code Execution - CWE-95 - showthread.php lines 1375, 1381
Old Code:
```php
$approveunapprovethread = "<option value=\"approvethread\">".$lang->approve_thread."</option>";
```
Fixed Code:
```php
eval("\$approveunapprovethread = \"".$templates->get("showthread_moderationoptions_approve")."\";");
```
Explanation:
The "fix" appears to introduce a code injection vulnerability rather than fix one. Using `eval()` with template content is dangerous and can allow arbitrary code execution if the template string is user-controlled. This is a step backward from hardcoded HTML. The original code using string concatenation with language variables was safer than using `eval()`. This change introduces CWE-95 (Code Injection) rather than fixing a vulnerability.
---
**Vulnerability 3: Template Injection via eval()**
Vulnerability Existed: not sure
Code Injection / Remote Code Execution - CWE-95 - showthread.php lines 1381
Old Code:
```php
$approveunapprovethread = "<option value=\"unapprovethread\">".$lang->unapprove_thread."</option>";
```
Fixed Code:
```php
eval("\$approveunapprovethread = \"".$templates->get("showthread_moderationoptions_unapprove")."\";");
```
Explanation:
Same concern as Vulnerability 2. The use of `eval()` with template output creates a code injection risk if the template system has any flaws or if template content can be poisoned. This is a potentially dangerous pattern.
--- cache/mybb_mybb_1807/stats.php 2025-12-06 11:32:55.298133214 +0000+++ cache/mybb_mybb_1808/stats.php 2025-12-06 11:32:56.030180484 +0000@@ -11,7 +11,8 @@ define("IN_MYBB", 1); define('THIS_SCRIPT', 'stats.php'); -$templatelist = "stats,stats_thread";+$templatelist = "stats,stats_thread,stats_topforum";+ require_once "./global.php"; require_once MYBB_ROOT."inc/functions_post.php"; require_once MYBB_ROOT."inc/class_parser.php";@@ -151,7 +152,8 @@ else { $forum['name'] = htmlspecialchars_uni(strip_tags($forum['name']));- $topforum = '<a href="'.get_forum_link($forum['fid'])."\">{$forum['name']}</a>";+ $forum['link'] = get_forum_link($forum['fid']);+ eval("\$topforum = \"".$templates->get("stats_topforum")."\";"); $topforumposts = $forum['posts']; $topforumthreads = $forum['threads']; }@@ -163,7 +165,7 @@ // Only show this if we have anything more the 0 referrals if($statistics['top_referrer']['referrals'] > 0) {- $toprefuser = build_profile_link($statistics['top_referrer']['username'], $statistics['top_referrer']['uid']);+ $toprefuser = build_profile_link(htmlspecialchars_uni($statistics['top_referrer']['username']), $statistics['top_referrer']['uid']); $top_referrer = $lang->sprintf($lang->top_referrer, $toprefuser, my_number_format($statistics['top_referrer']['referrals'])); } }@@ -182,7 +184,7 @@ } else {- $topposter = build_profile_link($statistics['top_poster']['username'], $statistics['top_poster']['uid']);+ $topposter = build_profile_link(htmlspecialchars_uni($statistics['top_poster']['username']), $statistics['top_poster']['uid']); } $topposterposts = $statistics['top_poster']['poststoday'];
I'll analyze this code diff for security vulnerabilities.
```
Vulnerability Existed: yes
TRUE POSITIVE
Code Injection via eval() - CWE-95 - stats.php Line 155
[Old Code]
$topforum = '<a href="'.get_forum_link($forum['fid'])."\">{$forum['name']}</a>";
[Fixed Code]
$forum['link'] = get_forum_link($forum['fid']);
eval("\$topforum = \"".$templates->get("stats_topforum")."\";");
Explanation:
While the old code was vulnerable to HTML injection via $forum['name'] (though mitigated by htmlspecialchars_uni on line 154), the "fix" introduces a MORE SERIOUS vulnerability. The use of eval() with template content is extremely dangerous. If the template "stats_topforum" contains any user-controlled data or is modifiable by attackers, this allows arbitrary code execution. The eval() statement directly executes PHP code constructed from the template string, which is a critical security anti-pattern. This is a regression - trading one vulnerability for a far more severe one.
```
```
Vulnerability Existed: not sure
Potential XSS via User Data - CWE-79 - stats.php Lines 168, 187
[Old Code]
$toprefuser = build_profile_link($statistics['top_referrer']['username'], $statistics['top_referrer']['uid']);
$topposter = build_profile_link($statistics['top_poster']['username'], $statistics['top_poster']['uid']);
[Fixed Code]
$toprefuser = build_profile_link(htmlspecialchars_uni($statistics['top_referrer']['username']), $statistics['top_referrer']['uid']);
$topposter = build_profile_link(htmlspecialchars_uni($statistics['top_poster']['username']), $statistics['top_poster']['uid']);
Explanation:
The addition of htmlspecialchars_uni() encoding on usernames is a positive security improvement that mitigates potential XSS vulnerabilities. The fix depends on whether build_profile_link() properly handles its first parameter. If build_profile_link() outputs the username in an HTML context without additional encoding, the old code was vulnerable to XSS attacks via malicious usernames. The htmlspecialchars_uni() encoding fixes this vulnerability by ensuring special characters are properly escaped before output.
```
--- cache/mybb_mybb_1807/usercp.php 2025-12-06 11:32:55.318134506 +0000+++ cache/mybb_mybb_1808/usercp.php 2025-12-06 11:32:56.030180484 +0000@@ -17,16 +17,16 @@ $templatelist .= ",usercp_attachments_attachment,usercp_attachments,usercp_profile_away,usercp_profile_customfield,usercp_profile_profilefields,usercp_profile_customtitle,usercp_forumsubscriptions_none,usercp_profile_customtitle_currentcustom"; $templatelist .= ",usercp_forumsubscriptions,usercp_subscriptions_none,usercp_subscriptions,usercp_options_pms_from_buddys,usercp_options_tppselect,usercp_options_pppselect,usercp_themeselector,usercp_profile_customtitle_reverttitle"; $templatelist .= ",usercp_nav_editsignature,usercp_referrals,usercp_notepad,usercp_latest_threads_threads,forumdisplay_thread_gotounread,usercp_latest_threads,usercp_subscriptions_remove,usercp_nav_messenger_folder,usercp_profile_profilefields_text";-$templatelist .= ",usercp_editsig_suspended,usercp_editsig,usercp_avatar_current,usercp_options_timezone_option,usercp_drafts";+$templatelist .= ",usercp_editsig_suspended,usercp_editsig,usercp_avatar_current,usercp_options_timezone_option,usercp_drafts,usercp_options_language,usercp_options_date_format,usercp_profile_website,usercp_latest_subscribed,usercp_warnings"; $templatelist .= ",usercp_avatar,usercp_editlists_userusercp_editlists,usercp_drafts_draft,usercp_usergroups_joingroup,usercp_attachments_none,usercp_avatar_upload,usercp_options_timezone,usercp_usergroups_joinable_usergroup_join";-$templatelist .= ",usercp_warnings_warning,usercp_warnings,usercp_latest_subscribed_threads,usercp_latest_subscribed,usercp_nav_messenger_tracking,multipage,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start,usercp_options_language,usercp_options_date_format";-$templatelist .= ",codebuttons,smilieinsert_getmore,smilieinsert_smilie,smilieinsert_smilie_empty,smilieinsert,usercp_nav_messenger_compose,usercp_options_language_option,usercp_editlists";+$templatelist .= ",usercp_warnings_warning,usercp_nav_messenger_tracking,multipage,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start";+$templatelist .= ",codebuttons,usercp_nav_messenger_compose,usercp_options_language_option,usercp_editlists,usercp_profile_contact_fields_field,usercp_latest_subscribed_threads,usercp_profile_contact_fields,usercp_profile_day"; $templatelist .= ",usercp_profile_profilefields_select_option,usercp_profile_profilefields_multiselect,usercp_profile_profilefields_select,usercp_profile_profilefields_textarea,usercp_profile_profilefields_radio,usercp_profile_profilefields_checkbox"; $templatelist .= ",usercp_options_tppselect_option,usercp_options_pppselect_option,forumbit_depth2_forum_lastpost_never,forumbit_depth2_forum_lastpost_hidden,usercp_avatar_auto_resize_auto,usercp_avatar_auto_resize_user,usercp_options"; $templatelist .= ",usercp_editlists_no_buddies,usercp_editlists_no_ignored,usercp_editlists_no_requests,usercp_editlists_received_requests,usercp_editlists_sent_requests,usercp_drafts_draft_thread,usercp_drafts_draft_forum"; $templatelist .= ",usercp_usergroups_leader_usergroup_memberlist,usercp_usergroups_leader_usergroup_moderaterequests,usercp_usergroups_memberof_usergroup_leaveprimary,usercp_usergroups_memberof_usergroup_display,usercp_email"; $templatelist .= ",usercp_usergroups_memberof_usergroup_leaveleader,usercp_usergroups_memberof_usergroup_leaveother,usercp_usergroups_memberof_usergroup_leave,usercp_usergroups_joinable_usergroup_description,usercp_options_time_format";-$templatelist .= ",usercp_editlists_sent_request,usercp_editlists_received_request,usercp_drafts_none,usercp_usergroups_memberof_usergroup_setdisplay,usercp_usergroups_memberof_usergroup_description,usercp_editlists_user,usercp_profile_day,usercp_profile_contact_fields,usercp_profile_contact_fields_field,usercp_profile_website";+$templatelist .= ",usercp_editlists_sent_request,usercp_editlists_received_request,usercp_drafts_none,usercp_usergroups_memberof_usergroup_setdisplay,usercp_usergroups_memberof_usergroup_description,usercp_editlists_user"; require_once "./global.php"; require_once MYBB_ROOT."inc/functions_post.php";@@ -44,8 +44,8 @@ if(!$mybb->user['pmfolders']) {- $mybb->user['pmfolders'] = "1**".$lang->folder_inbox."$%%$2**".$lang->folder_sent_items."$%%$3**".$lang->folder_drafts."$%%$4**".$lang->folder_trash;- $db->update_query("users", array('pmfolders' => $mybb->user['pmfolders']), "uid='".$mybb->user['uid']."'");+ $mybb->user['pmfolders'] = '1**$%%$2**$%%$3**$%%$4**';+ $db->update_query('users', array('pmfolders' => $mybb->user['pmfolders']), "uid = {$mybb->user['uid']}"); } $errors = '';@@ -57,67 +57,19 @@ $plugins->run_hooks("usercp_start"); if($mybb->input['action'] == "do_editsig" && $mybb->request_method == "post") {- $parser_options = array(- 'allow_html' => $mybb->settings['sightml'],- 'filter_badwords' => 1,- 'allow_mycode' => $mybb->settings['sigmycode'],- 'allow_smilies' => $mybb->settings['sigsmilies'],- 'allow_imgcode' => $mybb->settings['sigimgcode'],- "filter_badwords" => 1+ require_once MYBB_ROOT."inc/datahandlers/user.php";+ $userhandler = new UserDataHandler();++ $data = array(+ 'uid' => $mybb->user['uid'],+ 'signature' => $mybb->get_input('signature'), ); - if($mybb->user['showimages'] != 1 && $mybb->user['uid'] != 0)- {- $parser_options['allow_imgcode'] = 0;- }+ $userhandler->set_data($data); - $parsed_sig = $parser->parse_message($mybb->get_input('signature'), $parser_options);- if((($mybb->settings['sigimgcode'] == 0 && $mybb->settings['sigsmilies'] != 1) &&- substr_count($parsed_sig, "<img") > 0) ||- (($mybb->settings['sigimgcode'] == 1 || $mybb->settings['sigsmilies'] == 1) &&- substr_count($parsed_sig, "<img") > $mybb->settings['maxsigimages'])- )- {- if($mybb->settings['sigimgcode'] == 1)- {- $imgsallowed = $mybb->settings['maxsigimages'];- }- else- {- $imgsallowed = 0;- }- $lang->too_many_sig_images2 = $lang->sprintf($lang->too_many_sig_images2, $imgsallowed);- $error = inline_error($lang->too_many_sig_images." ".$lang->too_many_sig_images2);- $mybb->input['preview'] = 1;- }- else if($mybb->settings['siglength'] > 0)- {- if($mybb->settings['sigcountmycode'] == 0)- {- $parsed_sig = $parser->text_parse_message($mybb->get_input('signature'));- }- else- {- $parsed_sig = $mybb->get_input('signature');- }- $parsed_sig = preg_replace("#\s#", "", $parsed_sig);- $sig_length = my_strlen($parsed_sig);- if($sig_length > $mybb->settings['siglength'])- {- $lang->sig_too_long = $lang->sprintf($lang->sig_too_long, $mybb->settings['siglength']);- if($sig_length - $mybb->settings['siglength'] > 1)- {- $lang->sig_too_long .= $lang->sprintf($lang->sig_remove_chars_plural, $sig_length-$mybb->settings['siglength']);- }- else- {- $lang->sig_too_long .= $lang->sig_remove_chars_singular;- }- $error = inline_error($lang->sig_too_long);- }- }- if(isset($error) || !empty($mybb->input['preview']))+ if(!$userhandler->verify_signature()) {+ $error = inline_error($userhandler->get_friendly_errors()); $mybb->input['action'] = "editsig"; } }@@ -244,7 +196,7 @@ ); // Set up user handler.- require_once "inc/datahandlers/user.php";+ require_once MYBB_ROOT."inc/datahandlers/user.php"; $userhandler = new UserDataHandler("update"); $user = array(@@ -279,7 +231,7 @@ $user[$cfield] = $mybb->get_input($cfield); } }- + if($mybb->usergroup['canchangewebsite'] == 1) { $user['website'] = $mybb->get_input('website');@@ -382,9 +334,9 @@ $ageselected = " selected=\"selected\""; } - if($user['website'] == "" || $user['website'] == "http://")+ if(!my_validate_url($user['website'])) {- $user['website'] = "http://";+ $user['website'] = ''; } else {@@ -412,7 +364,7 @@ $contact_fields = array(); $contactfields = ''; $cfieldsshow = false;- + foreach(array('icq', 'aim', 'yahoo', 'skype', 'google') as $cfield) { $contact_fields[$cfield] = '';@@ -743,7 +695,7 @@ $user['usertitle'] = $mybb->user['usertitle']; } }- + $user['usertitle'] = htmlspecialchars_uni($user['usertitle']); $currentcustom = $reverttitle = '';@@ -756,7 +708,7 @@ eval("\$reverttitle = \"".$templates->get("usercp_profile_customtitle_reverttitle")."\";"); } }- + eval("\$customtitle = \"".$templates->get("usercp_profile_customtitle")."\";"); } else@@ -768,7 +720,7 @@ { eval("\$website = \"".$templates->get("usercp_profile_website")."\";"); }- + $plugins->run_hooks("usercp_profile_end"); eval("\$editprofile = \"".$templates->get("usercp_profile")."\";");@@ -834,7 +786,6 @@ $userhandler->set_data($user); - if(!$userhandler->validate_user()) { $errors = $userhandler->get_friendly_errors();@@ -1051,7 +1002,7 @@ { $pmnotifycheck = ''; }- + if(isset($user['buddyrequestspm']) && $user['buddyrequestspm'] != 0) { $buddyrequestspmcheck = "checked=\"checked\"";@@ -1207,7 +1158,7 @@ else { // Set up user handler.- require_once "inc/datahandlers/user.php";+ require_once MYBB_ROOT."inc/datahandlers/user.php"; $userhandler = new UserDataHandler("update"); $user = array(@@ -1303,7 +1254,7 @@ else { // Set up user handler.- require_once "inc/datahandlers/user.php";+ require_once MYBB_ROOT."inc/datahandlers/user.php"; $userhandler = new UserDataHandler("update"); $user = array(@@ -1365,7 +1316,7 @@ else { // Set up user handler.- require_once "inc/datahandlers/user.php";+ require_once MYBB_ROOT."inc/datahandlers/user.php"; $userhandler = new UserDataHandler("update"); $user = array(@@ -1553,34 +1504,19 @@ if(!empty($subscriptions)) { $tids = implode(",", array_keys($subscriptions));-- if($mybb->user['uid'] == 0)- {- // Build a forum cache.- $query = $db->simple_select('forums', 'fid', 'active != 0', array('order_by' => 'pid, disporder'));-- $forumsread = my_unserialize($mybb->cookies['mybb']['forumread']);- }- else- {- // Build a forum cache.- $query = $db->query("- SELECT f.fid, fr.dateline AS lastread- FROM ".TABLE_PREFIX."forums f- LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid=f.fid AND fr.uid='{$mybb->user['uid']}')- WHERE f.active != 0- ORDER BY pid, disporder- ");- }+ $readforums = array();+ + // Build a forum cache.+ $query = $db->query("+ SELECT f.fid, fr.dateline AS lastread+ FROM ".TABLE_PREFIX."forums f+ LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid=f.fid AND fr.uid='{$mybb->user['uid']}')+ WHERE f.active != 0+ ORDER BY pid, disporder+ ");+ while($forum = $db->fetch_array($query)) {- if($mybb->user['uid'] == 0)- {- if($forumsread[$forum['fid']])- {- $forum['lastread'] = $forumsread[$forum['fid']];- }- } $readforums[$forum['fid']] = $forum['lastread']; } @@ -1661,7 +1597,7 @@ $donenew = 0; $lastread = 0; - if($mybb->settings['threadreadcut'] > 0 && $mybb->user['uid'])+ if($mybb->settings['threadreadcut'] > 0) { $forum_read = $readforums[$thread['fid']]; @@ -1671,10 +1607,6 @@ $forum_read = $read_cutoff; } }- else- {- $forum_read = $forumsread[$thread['fid']];- } $cutoff = 0; if($mybb->settings['threadreadcut'] > 0 && $thread['lastpost'] > $forum_read)@@ -1743,7 +1675,7 @@ // Build last post info $lastpostdate = my_date('relative', $thread['lastpost']);- $lastposter = $thread['lastposter'];+ $lastposter = htmlspecialchars_uni($thread['lastposter']); $lastposteruid = $thread['lastposteruid']; // Don't link to guest's profiles (they have no profile).@@ -1794,42 +1726,17 @@ { $plugins->run_hooks("usercp_forumsubscriptions_start"); - if($mybb->user['uid'] == 0)- {- // Build a forum cache.- $query = $db->query("- SELECT fid- FROM ".TABLE_PREFIX."forums- WHERE active != 0- ORDER BY pid, disporder- ");-- if(isset($mybb->cookies['mybb']['forumread']))- {- $forumsread = my_unserialize($mybb->cookies['mybb']['forumread']);- }- }- else- {- // Build a forum cache.- $query = $db->query("- SELECT f.fid, fr.dateline AS lastread- FROM ".TABLE_PREFIX."forums f- LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid=f.fid AND fr.uid='{$mybb->user['uid']}')- WHERE f.active != 0- ORDER BY pid, disporder- ");- }+ // Build a forum cache.+ $query = $db->query("+ SELECT f.fid, fr.dateline AS lastread+ FROM ".TABLE_PREFIX."forums f+ LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid=f.fid AND fr.uid='{$mybb->user['uid']}')+ WHERE f.active != 0+ ORDER BY pid, disporder+ "); $readforums = array(); while($forum = $db->fetch_array($query)) {- if($mybb->user['uid'] == 0)- {- if($forumsread[$forum['fid']])- {- $forum['lastread'] = $forumsread[$forum['fid']];- }- } $readforums[$forum['fid']] = $forum['lastread']; } @@ -1885,7 +1792,7 @@ $forum['lastpostsubject'] = $parser->parse_badwords($forum['lastpostsubject']); $lastpost_date = my_date('relative', $forum['lastpost']); $lastposttid = $forum['lastposttid'];- $lastposter = $forum['lastposter'];+ $lastposter = htmlspecialchars_uni($forum['lastposter']); $lastpost_profilelink = build_profile_link($lastposter, $forum['lastposteruid']); $full_lastpost_subject = $lastpost_subject = htmlspecialchars_uni($forum['lastpostsubject']); if(my_strlen($lastpost_subject) > 25)@@ -2004,7 +1911,7 @@ "filter_badwords" => 1 ); - if($mybb->user['showimages'] != 1 && $mybb->user['uid'] != 0)+ if($mybb->user['showimages'] != 1) { $sig_parser['allow_imgcode'] = 0; }@@ -2242,7 +2149,7 @@ { $avatarmsg = "<br /><strong>".$lang->already_uploaded_avatar."</strong>"; }- elseif($mybb->user['avatartype'] == "remote" || my_strpos(my_strtolower($mybb->user['avatar']), "http://") !== false)+ elseif($mybb->user['avatartype'] == "remote" || my_validate_url($mybb->user['avatar'])) { $avatarmsg = "<br /><strong>".$lang->using_remote_avatar."</strong>"; $avatarurl = htmlspecialchars_uni($mybb->user['avatar']);@@ -2308,9 +2215,9 @@ { error($lang->invalid_request); }- + $plugins->run_hooks("usercp_acceptrequest_start");- + $user = get_user($request['uid']); if(!empty($user)) {@@ -2323,9 +2230,9 @@ { $user['buddylist'] = array(); }- + $user['buddylist'][] = (int)$mybb->user['uid'];- + // Now we have the new list, so throw it all back together $new_list = implode(",", $user['buddylist']); @@ -2341,12 +2248,12 @@ { $new_list = my_substr($new_list, 0, my_strlen($new_list)-2); }- + $user['buddylist'] = $db->escape_string($new_list);- + $db->update_query("users", array('buddylist' => $user['buddylist']), "uid='".(int)$user['uid']."'");- - ++ // We want to add the user to our buddy list if($mybb->user['buddylist'] != '') {@@ -2356,9 +2263,9 @@ { $mybb->user['buddylist'] = array(); }- + $mybb->user['buddylist'][] = (int)$request['uid'];- + // Now we have the new list, so throw it all back together $new_list = implode(",", $mybb->user['buddylist']); @@ -2374,11 +2281,11 @@ { $new_list = my_substr($new_list, 0, my_strlen($new_list)-2); }- + $mybb->user['buddylist'] = $db->escape_string($new_list);- + $db->update_query("users", array('buddylist' => $mybb->user['buddylist']), "uid='".(int)$mybb->user['uid']."'");- + $pm = array( 'subject' => 'buddyrequest_accepted_request', 'message' => 'buddyrequest_accepted_request_message',@@ -2386,25 +2293,26 @@ 'language' => $user['language'], 'language_file' => 'usercp' );- + send_pm($pm, $mybb->user['uid'], true);- + $db->delete_query('buddyrequests', 'id='.(int)$request['id']); } else { error($lang->user_doesnt_exist); }- + $plugins->run_hooks("usercp_acceptrequest_end");- + redirect("usercp.php?action=editlists", $lang->buddyrequest_accepted); }+ elseif($mybb->input['action'] == "declinerequest") { // Verify incoming POST request verify_post_check($mybb->get_input('my_post_key'));- + // Validate request $query = $db->simple_select('buddyrequests', '*', 'id='.$mybb->get_input('id', MyBB::INPUT_INT).' AND touid='.(int)$mybb->user['uid']); $request = $db->fetch_array($query);@@ -2412,9 +2320,9 @@ { error($lang->invalid_request); }- + $plugins->run_hooks("usercp_declinerequest_start");- + $user = get_user($request['uid']); if(!empty($user)) {@@ -2426,14 +2334,15 @@ } $plugins->run_hooks("usercp_declinerequest_end");- + redirect("usercp.php?action=editlists", $lang->buddyrequest_declined); }+ elseif($mybb->input['action'] == "cancelrequest") { // Verify incoming POST request verify_post_check($mybb->get_input('my_post_key'));- + // Validate request $query = $db->simple_select('buddyrequests', '*', 'id='.$mybb->get_input('id', MyBB::INPUT_INT).' AND uid='.(int)$mybb->user['uid']); $request = $db->fetch_array($query);@@ -2441,13 +2350,13 @@ { error($lang->invalid_request); }- + $plugins->run_hooks("usercp_cancelrequest_start");- + $db->delete_query('buddyrequests', 'id='.(int)$request['id']); $plugins->run_hooks("usercp_cancelrequest_end");- + redirect("usercp.php?action=editlists", $lang->buddyrequest_cancelled); } @@ -2515,7 +2424,7 @@ } $users[$key] = $db->escape_string($username); }- + // Get the requests we have sent that are still pending $query = $db->simple_select('buddyrequests', 'touid', 'uid='.(int)$mybb->user['uid']); $requests = array();@@ -2523,7 +2432,7 @@ { $requests[$req['touid']] = true; }- + // Get the requests we have received that are still pending $query = $db->simple_select('buddyrequests', 'uid', 'touid='.(int)$mybb->user['uid']); $requests_rec = array();@@ -2531,7 +2440,7 @@ { $requests_rec[$req['uid']] = true; }- + $sent = false; // Fetch out new users@@ -2586,11 +2495,11 @@ { $error_message = $lang->users_already_sent_request_alt; }- + array_pop($users); // To maintain a proper count when we call count($users) continue; }- + if(isset($requests_rec[$user['uid']])) { if($mybb->get_input('manage') != "ignored")@@ -2601,7 +2510,7 @@ { $error_message = $lang->users_already_rec_request_alt; }- + array_pop($users); // To maintain a proper count when we call count($users) continue; }@@ -2610,7 +2519,7 @@ if($user['buddyrequestsauto'] == 1 && $mybb->get_input('manage') != "ignored") { $existing_users[] = $user['uid'];- + $pm = array( 'subject' => 'buddyrequest_new_buddy', 'message' => 'buddyrequest_new_buddy_message',@@ -2619,14 +2528,14 @@ 'language' => $user['language'], 'language_file' => 'usercp' );- + send_pm($pm); } elseif($user['buddyrequestsauto'] != 1 && $mybb->get_input('manage') != "ignored") { // Send request $id = $db->insert_query('buddyrequests', array('uid' => (int)$mybb->user['uid'], 'touid' => (int)$user['uid'], 'date' => TIME_NOW));- + $pm = array( 'subject' => 'buddyrequest_received', 'message' => 'buddyrequest_received_message',@@ -2635,9 +2544,9 @@ 'language' => $user['language'], 'language_file' => 'usercp' );- + send_pm($pm);- + $sent = true; } elseif($mybb->get_input('manage') == "ignored")@@ -2684,7 +2593,7 @@ if(count($existing_users) == 0) { $message = "";- + if($sent === true) { $message = $lang->buddyrequests_sent_success;@@ -2712,10 +2621,10 @@ { $user['buddylist'] = array(); }- + $key = array_search($mybb->get_input('delete', MyBB::INPUT_INT), $user['buddylist']); unset($user['buddylist'][$key]);- + // Now we have the new list, so throw it all back together $new_list = implode(",", $user['buddylist']); @@ -2731,12 +2640,12 @@ { $new_list = my_substr($new_list, 0, my_strlen($new_list)-2); }- + $user['buddylist'] = $db->escape_string($new_list);- + $db->update_query("users", array('buddylist' => $user['buddylist']), "uid='".(int)$user['uid']."'"); }- + if($mybb->get_input('manage') == "ignored") { $message = $lang->removed_from_ignore_list;@@ -2745,6 +2654,7 @@ { $message = $lang->removed_from_buddy_list; }+ $user['username'] = htmlspecialchars_uni($user['username']); $message = $lang->sprintf($message, $user['username']); } }@@ -2797,12 +2707,12 @@ $message_js = ''; if($message) {- $message_js = "$.jGrowl('{$message}');";+ $message_js = "$.jGrowl('{$message}', {theme:'jgrowl_success'});"; } if($error_message) {- $message_js .= " $.jGrowl('{$error_message}');";+ $message_js .= " $.jGrowl('{$error_message}', {theme:'jgrowl_error'});"; } if($mybb->get_input('delete', MyBB::INPUT_INT))@@ -2855,6 +2765,7 @@ $query = $db->simple_select("users", "*", "uid IN ({$mybb->user['buddylist']})", array("order_by" => "username")); while($user = $db->fetch_array($query)) {+ $user['username'] = htmlspecialchars_uni($user['username']); $profile_link = build_profile_link(format_name($user['username'], $user['usergroup'], $user['displaygroup']), $user['uid']); if($user['lastactive'] > $timecut && ($user['invisible'] == 0 || $mybb->usergroup['canviewwolinvis'] == 1) && $user['lastvisit'] != $user['lastactive']) {@@ -2884,6 +2795,7 @@ $query = $db->simple_select("users", "*", "uid IN ({$mybb->user['ignorelist']})", array("order_by" => "username")); while($user = $db->fetch_array($query)) {+ $user['username'] = htmlspecialchars_uni($user['username']); $profile_link = build_profile_link(format_name($user['username'], $user['usergroup'], $user['displaygroup']), $user['uid']); if($user['lastactive'] > $timecut && ($user['invisible'] == 0 || $mybb->usergroup['canviewwolinvis'] == 1) && $user['lastvisit'] != $user['lastactive']) {@@ -2930,14 +2842,14 @@ $request['date'] = my_date($mybb->settings['dateformat'], $request['date'])." ".my_date($mybb->settings['timeformat'], $request['date']); eval("\$sent_rows .= \"".$templates->get("usercp_editlists_sent_request", 1, 0)."\";"); }- + if($sent_rows == '') { eval("\$sent_rows = \"".$templates->get("usercp_editlists_no_requests", 1, 0)."\";"); }- + eval("\$sent_requests = \"".$templates->get("usercp_editlists_sent_requests", 1, 0)."\";");- + echo $sentrequests; echo $sent_requests."<script type=\"text/javascript\">{$message_js}</script>"; }@@ -2949,7 +2861,7 @@ } exit; }- + $received_rows = ''; $query = $db->query(" SELECT r.*, u.username@@ -2964,14 +2876,14 @@ $request['date'] = my_date($mybb->settings['dateformat'], $request['date'])." ".my_date($mybb->settings['timeformat'], $request['date']); eval("\$received_rows .= \"".$templates->get("usercp_editlists_received_request")."\";"); }- + if($received_rows == '') { eval("\$received_rows = \"".$templates->get("usercp_editlists_no_requests")."\";"); }- + eval("\$received_requests = \"".$templates->get("usercp_editlists_received_requests")."\";");- + $sent_rows = ''; $query = $db->query(" SELECT r.*, u.username@@ -2986,14 +2898,14 @@ $request['date'] = my_date($mybb->settings['dateformat'], $request['date'])." ".my_date($mybb->settings['timeformat'], $request['date']); eval("\$sent_rows .= \"".$templates->get("usercp_editlists_sent_request")."\";"); }- + if($sent_rows == '') { eval("\$sent_rows = \"".$templates->get("usercp_editlists_no_requests")."\";"); }- + eval("\$sent_requests = \"".$templates->get("usercp_editlists_sent_requests")."\";");- + $plugins->run_hooks("usercp_editlists_end"); eval("\$listpage = \"".$templates->get("usercp_editlists")."\";");@@ -3228,7 +3140,7 @@ // Load language $lang->set_language($leader['language']); $lang->load("messages");- + $subject = $lang->sprintf($lang->emailsubject_newjoinrequest, $mybb->settings['bbname']); $message = $lang->sprintf($lang->email_groupleader_joinrequest, $leader['username'], $mybb->user['username'], $usergroup['title'], $mybb->settings['bbname'], $mybb->get_input('reason'), $mybb->settings['bburl'], $leader['gid']); my_mail($leader['email'], $subject, $message);@@ -3238,7 +3150,7 @@ // Load language $lang->set_language($mybb->user['language']); $lang->load("messages");- + $plugins->run_hooks("usercp_usergroups_join_group_request"); redirect("usercp.php?action=usergroups", $lang->group_join_requestsent); exit;@@ -3475,7 +3387,7 @@ $usergroupleaders = ''; foreach($groupleaders[$usergroup['gid']] as $leader) {- $leader['username'] = format_name($leader['username'], $leader['usergroup'], $leader['displaygroup']);+ $leader['username'] = format_name(htmlspecialchars_uni($leader['username']), $leader['usergroup'], $leader['displaygroup']); $usergroupleaders .= $comma.build_profile_link($leader['username'], $leader['uid']); $comma = $lang->comma; }@@ -3742,6 +3654,7 @@ $warning['postlink'] = get_post_link($warning['pid']); eval("\$post_link .= \"".$templates->get("usercp_warnings_warning_post")."\";"); }+ $warning['username'] = htmlspecialchars_uni($warning['username']); $issuedby = build_profile_link($warning['username'], $warning['issuedby']); $date_issued = my_date('relative', $warning['dateline']); if($warning['type_title'])@@ -3788,7 +3701,7 @@ } // Format username- $username = format_name($mybb->user['username'], $mybb->user['usergroup'], $mybb->user['displaygroup']);+ $username = format_name(htmlspecialchars_uni($mybb->user['username']), $mybb->user['usergroup'], $mybb->user['displaygroup']); $username = build_profile_link($username, $mybb->user['uid']); // Format post numbers@@ -3940,7 +3853,7 @@ } $lastpostdate = my_date('relative', $thread['lastpost']);- $lastposter = $thread['lastposter'];+ $lastposter = htmlspecialchars_uni($thread['lastposter']); $lastposteruid = $thread['lastposteruid']; if($lastposteruid == 0)@@ -3954,6 +3867,7 @@ $thread['replies'] = my_number_format($thread['replies']); $thread['views'] = my_number_format($thread['views']);+ $thread['username'] = htmlspecialchars_uni($thread['username']); $thread['author'] = build_profile_link($thread['username'], $thread['uid']); eval("\$latest_subscribed_threads .= \"".$templates->get("usercp_latest_subscribed_threads")."\";");@@ -4016,6 +3930,7 @@ if(!empty($threadcache)) { $tids = implode(",", array_keys($threadcache));+ $readforums = array(); // Read Forums $query = $db->query("@@ -4025,6 +3940,7 @@ WHERE f.active != 0 ORDER BY pid, disporder ");+ while($forum = $db->fetch_array($query)) { $readforums[$forum['fid']] = $forum['lastread'];@@ -4180,7 +4096,7 @@ $folder .= "folder"; $lastpostdate = my_date('relative', $thread['lastpost']);- $lastposter = $thread['lastposter'];+ $lastposter = htmlspecialchars_uni($thread['lastposter']); $lastposteruid = $thread['lastposteruid']; if($lastposteruid == 0)@@ -4194,6 +4110,7 @@ $thread['replies'] = my_number_format($thread['replies']); $thread['views'] = my_number_format($thread['views']);+ $thread['username'] = htmlspecialchars_uni($thread['username']); $thread['author'] = build_profile_link($thread['username'], $thread['uid']); eval("\$latest_threads_threads .= \"".$templates->get("usercp_latest_threads_threads")."\";");@@ -4208,4 +4125,3 @@ eval("\$usercp = \"".$templates->get("usercp")."\";"); output_page($usercp); }-
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - usercp.php lines 1675, 1792, 2654, 2765, 2795, 3387, 3657, 3704, 3867, 4110
Old Code:
```php
$lastposter = $thread['lastposter'];
$lastposter = $forum['lastposter'];
$message = $lang->sprintf($message, $user['username']);
$profile_link = build_profile_link(format_name($user['username'], $user['usergroup'], $user['displaygroup']), $user['uid']);
$leader['username'] = format_name($leader['username'], $leader['usergroup'], $leader['displaygroup']);
$username = format_name($mybb->user['username'], $mybb->user['usergroup'], $mybb->user['displaygroup']);
$issuedby = build_profile_link($warning['username'], $warning['issuedby']);
$thread['author'] = build_profile_link($thread['username'], $thread['uid']);
```
Fixed Code:
```php
$lastposter = htmlspecialchars_uni($thread['lastposter']);
$lastposter = htmlspecialchars_uni($forum['lastposter']);
$user['username'] = htmlspecialchars_uni($user['username']);
$user['username'] = htmlspecialchars_uni($user['username']);
$leader['username'] = format_name(htmlspecialchars_uni($leader['username']), $leader['usergroup'], $leader['displaygroup']);
$username = format_name(htmlspecialchars_uni($mybb->user['username']), $mybb->user['usergroup'], $mybb->user['displaygroup']);
$warning['username'] = htmlspecialchars_uni($warning['username']);
$thread['username'] = htmlspecialchars_uni($thread['username']);
```
Explanation:
The fix properly escapes user-controlled data (usernames, poster names) before using them in output contexts. These values are fetched from the database and used in HTML templates via `eval()` and `build_profile_link()`. Without escaping, an attacker could inject malicious JavaScript through specially crafted usernames stored in the database. The `htmlspecialchars_uni()` function converts special characters to HTML entities, preventing script execution. This is a critical vulnerability because usernames are user-controllable input that reaches output without sanitization.
---
Vulnerability Existed: yes
TRUE POSITIVE
SQL Injection - CWE-89 - usercp.php line 47
Old Code:
```php
$db->update_query("users", array('pmfolders' => $mybb->user['pmfolders']), "uid='".$mybb->user['uid']."'");
```
Fixed Code:
```php
$db->update_query('users', array('pmfolders' => $mybb->user['pmfolders']), "uid = {$mybb->user['uid']}");
```
Explanation:
While the fix changes the query syntax, the vulnerability assessment requires clarification. The old code concatenates `$mybb->user['uid']` directly into the WHERE clause with quotes. However, `uid` is a numeric field from the authenticated user's session. The fix removes quotes and uses string interpolation. Both approaches are vulnerable IF the uid value isn't validated as numeric. The proper fix would involve parameterized queries or explicit type casting. The current "fix" doesn't definitively eliminate SQL injection risk unless the MyBB framework guarantees uid is always numeric. This is "not sure" territory, but the removal of quotes suggests the developers recognized a potential issue with string concatenation.
---
Vulnerability Existed: yes
FALSE POSITIVE
Insecure Direct Object Reference / Logic Error - CWE-639 - usercp.php lines 1553-1573, 1726-1745
Old Code:
```php
if($mybb->user['uid'] == 0)
{
// Build a forum cache (guest logic)
...
}
else
{
// Build a forum cache (authenticated user logic)
...
}
```
Fixed Code:
```php
// Build a forum cache - only authenticated user logic
$query = $db->query("
SELECT f.fid, fr.dateline AS lastread
FROM ".TABLE_PREFIX."forums f
LEFT JOIN ".TABLE_PREFIX."forumsread fr ON (fr.fid=f.fid AND fr.uid='{$mybb->user['uid']}')
WHERE f.active != 0
ORDER BY pid, disporder
");
```
Explanation:
The fix removes guest user (uid=0) handling that relied on browser cookies for forum read tracking. This eliminates a potential authorization bypass where guest users could manipulate their `forumread` cookie to fake read status. By removing the cookie-based path entirely and only supporting authenticated users, the code becomes more secure. Guest users are now treated with the same database-backed read tracking as authenticated users, or more likely, guests don't get personalized read tracking at all. This prevents cookie tampering attacks against the forum read status feature.
--- cache/mybb_mybb_1807/warnings.php 2025-12-06 11:32:55.318134506 +0000+++ cache/mybb_mybb_1808/warnings.php 2025-12-06 11:32:56.030180484 +0000@@ -11,9 +11,9 @@ define("IN_MYBB", 1); define('THIS_SCRIPT', 'warnings.php'); -$templatelist = "warnings,warnings_warn_post,warnings_active_header,warnings_expired_header,warnings_warning,warnings_warn_existing,warnings_warn_type,warnings_warn_custom,warnings_warn_pm";-$templatelist .= ",warnings_view_post,warnings_view_user,warnings_view_revoke,warnings_view_revoked,smilieinsert_getmore,smilieinsert_smilie,smilieinsert_smilie_empty,smilieinsert,warnings_warn_type_result";-$templatelist .= ",multipage,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start,warnings_no_warnings,codebuttons,warnings_warn,warnings_view,warnings_warn_pm_anonymous";+$templatelist = "warnings,warnings_warn_post,warnings_active_header,warnings_expired_header,warnings_warning,warnings_warn_existing,warnings_warn_type,warnings_warn_custom,warnings_warn_pm,warnings_view";+$templatelist .= ",warnings_view_post,warnings_view_user,warnings_view_revoke,warnings_view_revoked,warnings_warn_type_result,warnings_postlink,codebuttons,warnings_warn,warnings_warn_pm_anonymous";+$templatelist .= ",multipage,multipage_end,multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage,multipage_start,warnings_no_warnings"; require_once "./global.php"; require_once MYBB_ROOT."inc/functions_warnings.php";@@ -249,6 +249,7 @@ $first = false; $post_link = "";+ $warning['username'] = htmlspecialchars_uni($warning['username']); $issuedby = build_profile_link($warning['username'], $warning['issuedby']); $date_issued = my_date('relative', $warning['dateline']); if($warning['type_title'])@@ -304,6 +305,7 @@ $send_pm_checked = ''; // Coming here from failed do_warn?+ $user['username'] = htmlspecialchars_uni($user['username']); if(!empty($warn_errors)) { $notes = htmlspecialchars_uni($mybb->get_input('notes'));@@ -584,6 +586,7 @@ { $user['username'] = $lang->guest; }+ $user['username'] = htmlspecialchars_uni($user['username']); $group_permissions = user_permissions($user['uid']); if($group_permissions['canreceivewarnings'] != 1)@@ -621,6 +624,7 @@ eval("\$warning_info = \"".$templates->get("warnings_view_user")."\";"); } + $warning['username'] = htmlspecialchars_uni($warning['username']); $issuedby = build_profile_link($warning['username'], $warning['issuedby']); $notes = nl2br(htmlspecialchars_uni($warning['notes'])); @@ -683,6 +687,7 @@ { $revoked_user['username'] = $lang->guest; }+ $revoked_user['username'] = htmlspecialchars_uni($revoked_user['username']); $revoked_by = build_profile_link($revoked_user['username'], $revoked_user['uid']); $revoke_reason = nl2br(htmlspecialchars_uni($warning['revokereason'])); eval("\$revoke = \"".$templates->get("warnings_view_revoked")."\";");@@ -714,6 +719,7 @@ error($lang->error_cant_warn_group); } + $user['username'] = htmlspecialchars_uni($user['username']); $lang->nav_profile = $lang->sprintf($lang->nav_profile, $user['username']); add_breadcrumb($lang->nav_profile, get_profile_link($user['uid'])); add_breadcrumb($lang->nav_warning_log);@@ -800,13 +806,16 @@ } $last_expired = $warning['expired']; - $post_link = "";+ $post_link = ''; if($warning['post_subject']) { $warning['post_subject'] = $parser->parse_badwords($warning['post_subject']); $warning['post_subject'] = htmlspecialchars_uni($warning['post_subject']);- $post_link = "<br /><small>{$lang->warning_for_post} <a href=\"".get_post_link($warning['pid'])."#pid{$warning['pid']}\">{$warning['post_subject']}</a></small>";+ $warning['post_link'] = get_post_link($warning['pid']);+ eval("\$post_link = \"".$templates->get("warnings_postlink")."\";"); }++ $warning['username'] = htmlspecialchars_uni($warning['username']); $issuedby = build_profile_link($warning['username'], $warning['issuedby']); $date_issued = my_date('relative', $warning['dateline']); if($warning['type_title'])
I'll analyze this code diff for security fixes.
Vulnerability Existed: yes
TRUE POSITIVE
Cross-Site Scripting (XSS) - CWE-79 - warnings.php [252, 308, 589, 627, 690, 722, 817]
Old Code:
```php
$issuedby = build_profile_link($warning['username'], $warning['issuedby']);
// (used directly without escaping $warning['username'])
$notes = htmlspecialchars_uni($mybb->get_input('notes'));
// (used $user['username'] without escaping)
$lang->nav_profile = $lang->sprintf($lang->nav_profile, $user['username']);
// (used $user['username'] directly in sprintf without escaping)
$post_link = "<br /><small>{$lang->warning_for_post} <a href=\"".get_post_link($warning['pid'])."#pid{$warning['pid']}\">{$warning['post_subject']}</a></small>";
// (concatenated directly into HTML without template escaping)
```
Fixed Code:
```php
$warning['username'] = htmlspecialchars_uni($warning['username']);
$issuedby = build_profile_link($warning['username'], $warning['issuedby']);
$user['username'] = htmlspecialchars_uni($user['username']);
$notes = htmlspecialchars_uni($mybb->get_input('notes'));
$user['username'] = htmlspecialchars_uni($user['username']);
$lang->nav_profile = $lang->sprintf($lang->nav_profile, $user['username']);
$warning['post_link'] = get_post_link($warning['pid']);
eval("\$post_link = \"".$templates->get("warnings_postlink")."\";");
```
Explanation:
This diff addresses multiple XSS vulnerabilities where user-controlled data (usernames from database) were being used in HTML context without proper escaping. The fix applies `htmlspecialchars_uni()` to escape these values before they're used in HTML output. Additionally, the hardcoded HTML string concatenation for the post link was refactored to use template rendering instead, which provides proper escaping through the template system. These changes prevent attackers from injecting malicious JavaScript through username fields or post subjects that could execute in other users' browsers.
--- cache/mybb_mybb_1807/xmlhttp.php 2025-12-06 11:32:55.318134506 +0000+++ cache/mybb_mybb_1808/xmlhttp.php 2025-12-06 11:32:56.030180484 +0000@@ -124,7 +124,7 @@ // Set the appropriate image language directory for this theme. // Are we linking to a remote theme server?-if(my_substr($theme['imgdir'], 0, 7) == 'http://' || my_substr($theme['imgdir'], 0, 8) == 'https://')+if(my_validate_url($theme['imgdir'])) { // If a language directory for the current language exists within the theme - we use it if(!empty($mybb->user['language']))@@ -255,7 +255,6 @@ if($limit == 1) { $user = $db->fetch_array($query);- $user['username'] = htmlspecialchars_uni($user['username']); $data = array('id' => $user['username'], 'text' => $user['username']); } else@@ -263,7 +262,6 @@ $data = array(); while($user = $db->fetch_array($query)) {- $user['username'] = htmlspecialchars_uni($user['username']); $data[] = array('id' => $user['username'], 'text' => $user['username']); } }@@ -578,6 +576,8 @@ "filter_badwords" => 1 ); + $post['username'] = htmlspecialchars_uni($post['username']);+ if($post['smilieoff'] == 1) { $parser_options['allow_smilies'] = 0;@@ -615,6 +615,7 @@ { $post['editdate'] = my_date('relative', TIME_NOW); $post['editnote'] = $lang->sprintf($lang->postbit_edited, $post['editdate']);+ $mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']); $post['editedprofilelink'] = build_profile_link($mybb->user['username'], $mybb->user['uid']); $post['editreason'] = trim($editreason); $editreason = "";@@ -1010,6 +1011,7 @@ $offline = array(); while($buddy = $db->fetch_array($query)) {+ $buddy['username'] = htmlspecialchars_uni($buddy['username']); $buddy_name = format_name($buddy['username'], $buddy['usergroup'], $buddy['displaygroup']); $profile_link = build_profile_link($buddy_name, $buddy['uid'], '_blank'); if($buddy['lastactive'] > $timecut && ($buddy['invisible'] == 0 || $mybb->user['usergroup'] == 4) && $buddy['lastvisit'] != $buddy['lastactive'])
# Security Analysis: xmlhttp.php Diff
I'll analyze this diff for security vulnerabilities following the specified format.
---
## Vulnerability 1: XSS - Removal of Output Encoding (Lines 258 & 265)
**Vulnerability Existed:** yes
**Cross-Site Scripting (XSS) - CWE-79** - xmlhttp.php lines 258, 265
**Old Code:**
```php
$user['username'] = htmlspecialchars_uni($user['username']);
$data = array('id' => $user['username'], 'text' => $user['username']);
```
**Fixed Code:**
```php
$data = array('id' => $user['username'], 'text' => $user['username']);
```
**Explanation:**
This is a **regression vulnerability**. The `htmlspecialchars_uni()` calls are being removed without corresponding protection added elsewhere. The username data is being returned in JSON response (based on context of AJAX handlers) and is no longer HTML-encoded at the source. If this data is later rendered as HTML without encoding, it creates an XSS vulnerability. However, if the JSON response is properly consumed by client-side JavaScript that doesn't interpret the values as HTML, the risk is mitigated. The removal suggests the developers may have moved encoding to the client-side or output layer, but this is a potentially dangerous refactor if not done correctly.
---
## Vulnerability 2: XSS - Missing Output Encoding Before HTML Output (Line 617)
**Vulnerability Existed:** not sure
**Cross-Site Scripting (XSS) - CWE-79** - xmlhttp.php line 617
**Old Code:**
```php
$post['editedprofilelink'] = build_profile_link($mybb->user['username'], $mybb->user['uid']);
```
**Fixed Code:**
```php
$mybb->user['username'] = htmlspecialchars_uni($mybb->user['username']);
$post['editedprofilelink'] = build_profile_link($mybb->user['username'], $mybb->user['uid']);
```
**Explanation:**
This appears to be a **security fix**. The `htmlspecialchars_uni()` encoding is added before passing `$mybb->user['username']` to `build_profile_link()`. This suggests the function accepts raw input and constructs HTML, so pre-encoding prevents XSS injection. However, without seeing the implementation of `build_profile_link()`, we cannot be completely certain if this fully prevents the vulnerability or if double-encoding might occur.
---
## Vulnerability 3: XSS - Missing Output Encoding (Line 579)
**Vulnerability Existed:** yes
**Cross-Site Scripting (XSS) - CWE-79** - xmlhttp.php line 579
**Old Code:**
```php
$data = array('id' => $user['username'], 'text' => $user['username']);
// (no encoding of $post['username'])
```
**Fixed Code:**
```php
$post['username'] = htmlspecialchars_uni($post['username']);
// ... used in HTML context later
```
**Explanation:**
This is a **security improvement**. The `$post['username']` is now HTML-encoded before use, preventing XSS if this data is rendered in HTML output. This protects against malicious usernames containing script tags or event handlers.
---
## Vulnerability 4: XSS - Missing Output Encoding (Line 1014)
**Vulnerability Existed:** yes
**Cross-Site Scripting (XSS) - CWE-79** - xmlhttp.php line 1014
**Old Code:**
```php
$buddy_name = format_name($buddy['username'], $buddy['usergroup'], $buddy['displaygroup']);
// (no prior encoding)
```
**Fixed Code:**
```php
$buddy['username'] = htmlspecialchars_uni($buddy['username']);
$buddy_name = format_name($buddy['username'], $buddy['usergroup'], $buddy['displaygroup']);
```
**Explanation:**
This is a **security improvement**. The `$buddy['username']` is encoded before being passed to `format_name()`, which likely constructs display names for HTML output. This prevents XSS attacks via malicious usernames in the buddy list feature.
---
## Vulnerability 5: URL Validation Change (Line 127)
**Vulnerability Existed:** not sure
**Improper Input Validation - CWE-20** - xmlhttp.php line 127
**Old Code:**
```php
if(my_substr($theme['imgdir'], 0, 7) == 'http://' || my_substr($theme['imgdir'], 0, 8) == 'https://')
```
**Fixed Code:**
```php
if(my_validate_url($theme['imgdir']))
```
**Explanation:**
This appears to be a **security improvement** assuming `my_validate_url()` performs proper URL validation. The old code only checks if the string *starts with* `http://` or `https://`, which is insufficient validation (doesn't verify actual URL format, could be bypassed with tricks). The new validation function should provide more robust checking. However, without seeing the `my_validate_url()` implementation, we cannot be certain it properly prevents SSRF or other URL-based attacks.
---
## Summary
- **Definite Regressions:** Line 258, 265 (removed XSS protection without replacement)
- **Definite Fixes:** Lines 579, 1014, 617 (added XSS protection)
- **Uncertain/Conditional:** Line 127 (depends on `my_validate_url()` implementation)