Запись 47. Броня для боевых серверов: Universal Command Guard, укрощение истории Bash и рентген буфера xterm
⏱️ Время: 26 сентября 2026, 17:45 (~40 минут)1. Повод: когда защитный тумблер щелкает в пустоту
В процессе живой проверки Shellit я зашел в карточку рабочего сервера со средой по умолчанию (defaultEnv), открыл редактирование и щелкнул тумблер: «Production Command Guard».
Казалось бы, намерение прозрачно: я явно приказал приложению блокировать деструктивные команды на этом узле. Сохраняю хост, подключаюсь по SSH, консоль разворачивается… и тишина. Никакой тревожной рамки, ни предупреждающего бейджа, ни перехвата команд. Я вбиваю опасную команду — и она без малейшего сопротивления улетает на сервер.
Диалог с нейросетью был предельно конкретным:
«проверь реализацию prod guard»
«не вижу никакого визуального отличия, в дополнение к выявленным тобой багам»
«все обнаруженные баги зафиксируй! потом обсудим план»
«надо как-то в описании самого тумблера указать на это. Кроме того, объясни мне, на что вообще влияет выбор пункта из этого выпадающего списка?»
2. Подводные камни: разрыв логики и каскад уязвимостей
Когда мы начали копать глубже одного визуального бага, наружу всплыл целый каскад критических архитектурных и эргономических проблем:
- Разрыв между тумблером и средой (
BUG-037): РамкаProdGuardBorderи условие в терминале проверяли исключительноhost.environment == HostEnvironment.production. Если сервер находился вdefaultEnv,stagingилиdevelopment, тумблер защиты превращался в «мертвый код» — настройки сохранялись в зашифрованную базу, но в терминале наглухо игнорировались. - Фатальный обход через историю Bash (
BUG-038, P0 Blocker): Классический буфер ввода_commandLineBufferпосимвольно накапливал печатные знаки из потока ввода, отбрасывая управляющие ANSI escape-коды. Стоило нажатьСтрелку вверх(Up Arrow), чтобы достать из истории шелла недавнюю команду вродеrm -rf /var/cache/*, как_commandLineBufferоставался девственно пустым! При нажатииEnterопасная команда моментально улетала на выполнение без единого диалога. - Дырки в регулярных выражениях (
BUG-039): Детектор деструктивных команд жил во внешнем UI-пакетеterminal_uiвместо доменного ядра и проверял\brm\s+. Команды с абсолютными путями (/bin/rm), обратным порядком флагов (rm -f -r) или современные системные утилиты (wipefs,truncate -s 0,systemctl poweroff/reboot,chmod -R 777) пролетали сквозь защиту. - Кошмар внутри nano и vim (
BUG-040): При редактировании файлов в полноэкранных TUI-редакторах каждое нажатиеEnterпродолжало анализироваться парсером шелла. Если в конфиге попадалась подстрока сrm, всплывал диалог подтверждения, а при его отмене терминал посылал сигналCtrl+C(\x03), немедленно ломая сеанс редактирования. - Рассинхрон с AI Gateway MCP (
BUG-041): В коде MCP-шлюза для внешних агентов стояла примитивная проверкаcontains('rm -rf'), расходящаяся с терминальным клиентом. - Нарушение Zero Hardcoded Strings и неинформативные вкладки (
BUG-042): Тексты баннеров были захардкожены на английском, а на вкладках сессий не было видно, в каком окружении работает открытый терминал.
3. Архитектурные решения и реализация
План исправления потребовал слаженной переработки нескольких слоев приложения:
1. Универсальный Command Guard и цветовая дифференциация
Мы превратили «Prod Guard» в полноценный Universal Command Guard:
- Если сервер объявлен как Production (
HostEnvironment.production), защита деструктивных действий активна всегда по умолчанию, а окно терминала обрамляется контрастной красной рамкой (2.5px,#FF3333) с бейджем[⚠️ PRODUCTION ENVIRONMENT]. - Если сервер находится в любом другом окружении (
defaultEnv,staging,development), но пользователь сознательно активировал тумблер «Command Guard», окно терминала выделяется защитной янтарной рамкой (2.0px,#FFB020) с бейджем[🛡️ COMMAND GUARD ACTIVE]. - В форме хоста тумблер переименован в «Command Guard (Destructive Protection)» и снабжен динамическим подзаголовком: он открыто сообщает, что для серверов Production защита активна всегда, а для остальных сред включается индивидуально.
2. Рентген буфера xterm и очистка системного промпта
Чтобы исключить обход защиты стрелками истории Bash, мы применили элегантный прием: при нажатии Enter терминал выполняет резервный снимок активной экранной строки:
final screenLine = _terminal.buffer.lines[_terminal.buffer.cursorY].toString();final candidate = DangerousCommandChecker.cleanPromptAndExtractCommand(screenLine);Новый статический метод cleanPromptAndExtractCommand виртуозно отсекает системные промпты любой сложности (user@server:~$ , root@srv:~# , (venv) [user@host /var]$ ), оставляя чистую команду для проверки. Если в строке обнаружена деструктивная операция, терминал мгновенно блокирует ввод и вызывает модальное подтверждение.
3. Уважение к Alternate Screen Buffer (TUI)
В терминальных эмуляторах при запуске vim, nano, htop или less происходит переключение в альтернативный буфер экрана (\x1b[?1049h). Библиотека xterm.dart предоставляет нативное свойство _terminal.isUsingAltBuffer. В самое начало обработчика ввода мы добавили лаконичную строку:
if (_terminal.isUsingAltBuffer) return;Внутри редакторов защита благоразумно отходит в сторону, позволяя спокойно нажимать Enter при правке файлов.
4. Доменное ядро и унификация в core_foundation
Класс DangerousCommandChecker переехал в packages/core_foundation/lib/src/security/dangerous_command_checker.dart. Регулярные выражения получили поддержку путей (?:[^\s]*\/)?, произвольного порядка ключей и полный арсенал опасных системных утилит (wipefs, truncate, dd, mkfs, systemctl, init 0, chmod -R). Этот же валидатор подключен в MCP Server Gateway.
5. Бейджи на табах и чистота локализации
В заголовках вкладок top_bar_tabs.dart появились цветные чипы окружений (PROD красный, STAGE янтарный, DEV синий), а рядом — индикатор [🛡️ GUARD]. Все пользовательские сообщения вынесены в context.tr('prod_guard.*') с полным русским переводом.
4. Итог: Релиз v0.8.6
- Закрыты все 6 инцидентов:
BUG-037—BUG-042. - Написаны 48 тестов детектора деструктивных команд в ядре и 9 регрессионных тестов в интерфейсе.
- Полный прогон тестов дал 100% зеленый результат:
core_foundation: 27/27 успешно.terminal_ui: 126/126 успешно.desktop_plugin_sdk: 62/62 успешно.apps/shellit: 61/61 успешно.
- Статический анализ
flutter analyzeпоказал 0 issues found. - Версия программы повышена до v0.8.6.
Защита боевых серверов в Shellit теперь работает на уровне интуиции: видна глазами, перехватывает команды независимо от способа ввода и не мешает повседневной работе в консольных редакторах.