Skip to content

[Bug] 13 багов: XSS через ExecuteJS, Substring crash, Convert без try-catch, EnglishName без Split #2

Description

@lkaliturin220-svg

🐛 Bug Report: BusEngine — Баги и исправления

Repository: https://github.com/BuslikDrev/BusEngine
Date: 2026-07-06
Analyzed: ~15 source files (C# + JS + PHP)


🔴 КРИТИЧЕСКИЕ БАГИ

BUG-1: XSS/Code Injection через ExecuteJS во всех обработчиках

Файл: BusEngine/Code/Plugin/Program.cs (строки 143, 277, 288)
Копия в: Templates/cs/Launcher/Code/Plugin/Program.cs (те же строки)

// Строка 143: сообщение напрямую в JS
_browser.ExecuteJS("document.dispatchEvent(new CustomEvent('BusEngineMessage', " +
    "{detail: {data: 'Получил твою команду! Вось яна: " + message + "'}}));");

// Строка 277: имя файла напрямую в JS
_browser.ExecuteJS("document.querySelector('" + t + "').value = '" +
    openFileDialog.FileName.Replace("\\", "\\\\") + "';");

// Строка 288: путь к папке напрямую в JS
_browser.ExecuteJS("document.querySelector('" + t + "').value = '" +
    folderBrowserDialog.SelectedPath.Replace("\\", "\\\\") + "';");

Проблема: Если имя файла/папки содержит ' или \, JavaScript ломается. Например, файл pwned');alert(1);//.txt выполнит произвольный JS.

Исправление:

// Экранировать спецсимволы перед вставкой в JS
private static string EscapeJsString(string s) {
    return s.Replace("\\", "\\\\").Replace("'", "\\'").Replace("\n", "\\n").Replace("\r", "");
}

_browser.ExecuteJS("document.querySelector('" + EscapeJsString(t) + 
    "').value = '" + EscapeJsString(openFileDialog.FileName) + "';");

BUG-2: IndexOutOfRangeException при коротком message

Файл: BusEngine/Code/Plugin/Program.cs:145
Копия в: Templates/cs/Launcher/Code/Plugin/Program.cs:126

} else {
    t = t.Substring(0, 8);  // ⚠ КРАШ если message.Length < 8!

Сценарий: Если веб-интерфейс пришлёт сообщение короче 8 символов (например, "test"), приложение упадёт с ArgumentOutOfRangeException.

Исправление:

} else {
    if (t.Length >= 8) {
        t = t.Substring(0, 8);
    } else {
        return;  // или BusEngine.Log.Info("Неизвестная команда: {0}", message);
    }

BUG-3: Convert.ToInt32 без try-catch — FormatException

Файлы:

  • Plugin/Program.cs (строки 157, 167, 171, 248, 252)
  • Game.cs:165-166, Editor.cs:161-162, GameAndroid.cs:162-163
nx = System.Convert.ToInt32(xy[0]);  // ⚠ КРАШ если не число!

Сценарий: Баг в JS или злонамеренное сообщение → _resize|abc 100 → приложение падает.

Исправление:

if (!int.TryParse(xy[0], out nx)) {
    BusEngine.Log.Info("Некорректный параметр: {0}", xy[0]);
    return;
}

🟡 СРЕДНИЕ БАГИ

BUG-4: Культура всегда Belarusian из-за EnglishName без Split

Файлы: Launcher.cs:142, Game.cs:111, Editor.cs:107, GameAndroid.cs:108

string lang = System.Globalization.CultureInfo.CurrentCulture.EnglishName;
// EnglishName = "English (United States)" — не равно "English"!
if (lang == "English") {  // ⚠ НИКОГДА не сработает

Исправление:

string lang = System.Globalization.CultureInfo.CurrentCulture.EnglishName.Split(' ')[0];
// Теперь lang = "English" ✓
if (lang == "English") {

Примечание: в Plugin/Program.cs:41 это сделано правильно через Split(' ')[0].


BUG-5: Логическая ошибка в setting['debug'] (JS)

Файл: BusEngine/Data/Scripts/BusEngine/BusEngine.js:146-148
Копия в: docs/Scripts/BusEngine/BusEngine.js

if (typeof setting['debug'] === 'boolean') {
    setting['debug'] = false;  // ⚠ Сбрасывает true в false!
}

Проблема: Если пользователь передал debug: true, оно принудительно сбрасывается в false. Должно быть !== 'boolean' (установить дефолт, только если не задано).

Исправление:

if (typeof setting['debug'] !== 'boolean') {
    setting['debug'] = false;
}

BUG-6: Перепутаны params/callback в BusEngine.open

Файл: BusEngine/Data/Scripts/BusEngine/BusEngine.js:275-281

if (typeof params !== 'function') {
    callback = function() {};  // ⚠ Затирает callback, но params может быть данными!
}

Проблема: Проверяется params, а затирается callback. Если params — объект с данными, а callback — функция, то callback теряется.

Исправление:

if (typeof callback !== 'function') {
    callback = function() {};
}

BUG-7: insertAdjacentHTML с неправильным регистром

Файл: BusEngine/Data/Scripts/BusEngine/BusEngine.js:341

element.insertAdjacentHTML('beforeEnd', e.innerHTML);  // ⚠ 'beforeEnd' → 'beforeend'

Спецификация требует 'beforeend' (нижний регистр). CEF/Chromium может быть tolerant, но некоторые браузеры — нет.

Исправление:

element.insertAdjacentHTML('beforeend', e.innerHTML);

🟢 МЕЛКИЕ БАГИ / КАЧЕСТВО КОДА

BUG-8: GC.Collect без return после ошибки (мёртвый код)

Файл: Launcher.cs:158-161

System.Windows.Forms.MessageBox.Show(desc, title, ...);
System.GC.WaitForPendingFinalizers();
System.GC.Collect();
// ⚠ Нет return! Программа продолжит работу с неполной инициализацией

Но фактически не достигается из-за структуры if/else. Удалить мёртвый код GC.Collect.


BUG-9: Дублирование кода в 4 файлах

Game.cs, Editor.cs, GameAndroid.cs, Launcher.cs содержат ~80% одинакового кода (Main, Form, CreateParams). Баги исправляются в 4 местах.

Рекомендация: Вынести общий код в базовый класс или shared library.


BUG-10: Application.Exit() + Environment.Exit(0) подряд

Файл: Launcher.cs:78-80

System.Windows.Forms.Application.Exit();
System.Environment.Exit(0);
return;  // ← никогда не выполнится

Environment.Exit(0) убивает процесс немедленно, не давая Application.Exit() корректно завершить message pump.

Исправление: Убрать Environment.Exit(0), оставить только Application.Exit() + return.


BUG-11: Хардкод Google API ключей

Файл: Plugin/Program.cs:119-121

System.Environment.SetEnvironmentVariable("google_api_key", "123");
System.Environment.SetEnvironmentVariable("google_default_client_id", "123.apps.googleusercontent.com");
System.Environment.SetEnvironmentVariable("google_default_client_secret", "123-123");

Фейковые ключи, но код в продакшене. Удалить или вынести в конфиг.


BUG-12: HandleProcessCorruptedStateExceptions без необходимости

Файлы: Game.cs:88, Editor.cs:84, GameAndroid.cs:85

[System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions]

Этот атрибут ловит AccessViolationException и другие критические ошибки, что может скрыть повреждение памяти. Используется только в паре с #if RUN_LOG. Убрать или ограничить областью видимости.


BUG-13: Загрузка внешних скриптов без проверки (XSS-риск)

Файл: BusEngine.js:364, 385

BusEngine.loadScript(scripts[i].src);  // любой URL!

Если в загружаемом HTML есть <script src="https://evil.com/payload.js">, он выполнится.

Исправление: Добавить белый список доменов или CSP.


📊 Сводка

# Баг Severity Файлы Сложность исправления
1 XSS через ExecuteJS 🔴 CRIT Plugin/Program.cs 30 мин
2 Substring без проверки длины 🔴 CRIT Plugin/Program.cs 5 мин
3 Convert без try-catch 🔴 CRIT 4 файла 15 мин
4 EnglishName без Split 🟡 MED 4 файла 5 мин
5 debug boolean инвертирован 🟡 MED BusEngine.js 1 мин
6 params/callback перепутаны 🟡 MED BusEngine.js 1 мин
7 insertAdjacentHTML регистр 🟡 MED BusEngine.js 1 мин
8 Мёртвый GC.Collect 🟢 LOW Launcher.cs 1 мин
9 Дублирование кода 🟢 LOW 4 файла рефакторинг
10 Двойной Exit 🟢 LOW Launcher.cs 1 мин
11 Хардкод ключей 🟢 LOW Plugin/Program.cs 5 мин
12 HandleProcessCorrupted 🟢 LOW 3 файла 1 мин
13 Внешние скрипты 🟢 LOW BusEngine.js 15 мин

Всего: 13 багов (3 CRIT, 4 MED, 6 LOW)


Report generated by Hermes Agent

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions