Skip to content

Releases: DeveloperrEva/conchshell

Conchshell 2.10.1

Choose a tag to compare

@github-actions github-actions released this 03 Aug 14:17

Download the .dmg for macOS (pick aarch64 for Apple Silicon,
x64 for Intel), the .msi or .exe for Windows, or the
.AppImage / .deb / .rpm for Linux.
Auto-updater artifacts (latest.json, *.sig) are included.

What changed: see CHANGES.md.

Conchshell 2.10.0

Choose a tag to compare

@github-actions github-actions released this 03 Aug 11:40

Download the .dmg for macOS (pick aarch64 for Apple Silicon,
x64 for Intel), the .msi or .exe for Windows, or the
.AppImage / .deb / .rpm for Linux.
Auto-updater artifacts (latest.json, *.sig) are included.

What changed: see CHANGES.md.

Conchshell 2.9.1 (macOS + Linux)

Choose a tag to compare

@github-actions github-actions released this 02 Aug 18:54

Conchshell для macOS (Apple Silicon) и Linux.
Скачивайте .dmg (macOS) либо .AppImage / .deb (Linux). Артефакты автообновления (latest.json, *.sig) приложены.


Главное: пароли больше не лежат открытым текстом

До этой версии сохранённые пароли, ключевые фразы и учётные данные прокси и jump-хостов хранились в localStorage — обычным текстом, в файле внутри каталога приложения. Их читал любой процесс от вашего имени, они уезжали в любой бэкап и находились обычным grep.

Теперь при первом запуске появляется мастер, который переносит их в зашифрованное хранилище: XChaCha20-Poly1305, ключ через Argon2id, отдельные независимые слоты ключей. Перенос идёт по схеме «записать → прочитать обратно с диска → сверить → только потом стереть открытую копию», поэтому сбой на любом шаге не может уничтожить единственный экземпляр пароля.

Команды чтения секрета не существует. Фронтенд может положить пароль в хранилище и удалить его, но получить обратно — нет. Учётные данные читает только Rust, в момент подключения. Скомпрометированное окно приложения не может выгрузить хранилище через IPC.

Мастер-пароль не нужен. Хранилище открывается ключом из keychain macOS, без запросов при запуске. Если хотите более строгий режим — «Настройки → Безопасность → Спрашивать мастер-пароль при запуске»; тогда хранилище остаётся запертым, пока вы не введёте пароль, и это защищает его и от всего, что работает на машине до первой разблокировки. Оба способа — независимые обёртки одного ключа, так что переключение туда-обратно ничего не перешифровывает и не обесценивает уже записанный пароль.

Честно о границах: ключ в обычном keychain читается любым процессом, работающим от вашего имени. То есть хранилище защищено настолько же, насколько ваша учётная запись macOS. Бэкап одного файла хранилища бесполезен — ключа в нём нет; бэкап вместе с login.keychain-db отдаёт ключ тому, у кого есть ваш пароль входа. Подробности — docs/vault-format.md, раздел 2.5.1.


Закрытые уязвимости

Три отдельных прохода аудита, каждая находка проверялась независимым агентом с задачей её опровергнуть.

Враждебный SSH-сервер мог записать файл в любое место диска. Вкладка «Files» получала листинг, разбирая вывод ls -la, и отбрасывала только строки . и ... Имя вида ../../../../.zshrc проходило и склеивалось с папкой, выбранной для загрузки, — содержимое тоже выбирал сервер. Дальше ~/.zshrc или ~/.ssh/authorized_keys и выполнение кода при следующем входе. Закрыто с трёх сторон, включая проверку в самой команде скачивания.

Терминал отвечал на запрос чтения буфера обмена. Последовательность OSC 52 ; c ; ? заставляла приложение прочитать системный буфер и отправить его обратно в stdin того же сервера. Для SSH-клиента со встроенным хранилищем это прямой способ увести пароль или ключ; ответ уходил как ввод, поэтому в raw-режиме на экране не появлялось ничего. Чтение теперь запрещено безусловно, настройки для него нет. Запись оставлена и включена по умолчанию — она нужна, например, чтобы копировать из vim через SSH.

Одно окно могло управлять сессиями другого. Аутентификация канала не мешала одному сокету писать в чужой терминал, менять его размер и получать его вывод. Теперь сообщение к живой сессии принимается только от сокета, который её создал.

Импорт known_hosts терял отзыв ключа. Строка @revoked * <ключ> — стандартный способ отозвать ключ везде — не разбиралась, и отозванный отпечаток мог попасть в доверенные, после чего соединение проходило вообще без вопросов.

Отключение соединений не работало. Двенадцать вызовов передавали аргументы в неверном регистре, команда их не находила и отклоняла — молча, потому что ошибку никто не показывал. Так не работали отключение SSH/SFTP/FTP и кнопка отмены подключения.

FTPS теперь закрепляет ключ сервера через тот же механизм, что SSH и RDP: первое подключение спрашивает доверие, изменившийся ключ — отказ. Заодно вернулась поддержка самоподписанных сертификатов, которых для FTPS большинство.


Новое

  • Выбор программы для открытия файлов. В редакторе появилось меню: открыть в системной программе по умолчанию, выбрать конкретную и запомнить её, забыть выбранную. Встроенный редактор остаётся значением по умолчанию для всего, что умеет показать.
  • Управление хранилищем в настройках — состояние, кнопка «Запереть», переключатель мастер-пароля.

Исправления

  • Мигрированное соединение нельзя было открыть из диалога: он требовал пароль в поле, которое миграция намеренно опустошила.
  • Правка пароля стирала сохранённые пароли прокси и jump-хоста.
  • Восстановление сессии стартовало при запертом хранилище, из-за чего все соединения падали при запуске.
  • Пароль прокси для RDP не доставался из хранилища.
  • Вкладка «Безопасность» состояла из трёх переключателей, не подключённых ни к чему. Опаснее прочих был «Host Key Verification»: он выглядел выключаемым, тогда как проверка ключа безусловна. Заменено на честный статус.
  • Импорт конфигурации по умолчанию заменял все соединения без предупреждения. Теперь по умолчанию объединение, а замена требует подтверждения с числом удаляемых записей.
  • Русские формы множественного числа существовали только для 1 и «многих», поэтому любое число от 2 до 20 показывалось по-английски. Добавлены недостающие формы, проверка покрытия переписана по категориям Intl.PluralRules.
  • Поправлена вёрстка в настройках: заголовок строки и надпись на кнопке использовали одну и ту же длинную строку.

Важно при обновлении

Это переходная версия смены ключа подписи обновлений. Сборки несут новый публичный ключ, но подписаны старым, потому что установленный клиент проверяет подпись тем ключом, который вкомпилирован в него самого. Обновление с 2.9.0 пройдёт штатно.

Ключ подписи в CI нельзя переключать на новый, пока эта версия не разойдётся, — иначе обновления оборвутся у всех, кто ещё на 2.9.0.


Что осталось открытым

Чтобы не создавать ложного впечатления. Команды Tauri не разграничены по правам: любое окно может вызвать любую команду по чужому идентификатору соединения, а решение о доверии к ключу сервера принимает сторона окна. Не проверялись аудитом: слой VNC, разбор протоколов SFTP/FTP и механизм самообновления целиком. Сборки под Windows не выпускаются и этот путь не проверялся.

Полный список изменений — CHANGES.md.

Conchshell 2.9.0 — релиз безопасности (обновитесь как можно скорее)

Choose a tag to compare

@github-actions github-actions released this 02 Aug 11:54

🔐 2.9.0 — обновитесь как можно скорее

Это релиз безопасности. Проведён аудит всего приложения по семи поверхностям атаки; найденное исправлено. Одна из находок — критическая.

🔴 Критично: удалённое выполнение кода

r-shell слушал локальный порт (9001) для связи терминала с бэкендом и принимал любое соединение — без пароля, без проверки, кто подключается. А команда «запусти локальный терминал» не требовала никаких условий: она сразу запускала вашу оболочку.

Из-за того, что WebSocket не подчиняется обычным правилам изоляции сайтов, подключиться мог не только другой процесс на вашем компьютере, но и любая веб-страница, которую вы открыли в браузере. То есть простое посещение сайта могло дать чужому коду полноценную командную строку от вашего имени — а дальше: пароли серверов (они пока хранятся открыто), ключи из ~/.ssh, подмена доверенных ключей серверов.

Исправлено: канал теперь требует секретный токен, который создаётся при каждом запуске и передаётся только самому приложению. Веб-страница получить его не может.

Остальное исправленное

  • Внедрение команд. Шесть операций с файлами и логами подставляли пути в команды без экранирования. Для одной из них путь приходит от самого сервера — достаточно было создать на нём файл с апострофом в имени, чтобы выполнить произвольную команду.
  • Выход за пределы папки при скачивании. Вредоносный SFTP/FTP-сервер мог подсунуть в списке файлов имя вида ../../../.zshrc и при скачивании папки записать файл куда угодно на вашем диске.
  • FTPS принимал любой сертификат. Соединение шифровалось, но не проверялось — то есть любой, кто может вклиниться в сеть, читал ваш пароль FTP. Теперь сертификат проверяется. Если ваш FTPS-сервер с самоподписанным сертификатом — подключение будет отклонено с понятным объяснением; это сделано намеренно.
  • Нажатия клавиш попадали в лог. При включённом отладочном логировании в файл писалось всё, что вы набирали, — включая пароль, введённый в sudo.
  • Пароль FTP в логах — закрыто.
  • Временные файлы редактора (при «Открыть в VS Code») создавались доступными для чтения всем локальным пользователям. Теперь только для вас.

Что стоит сделать

Если вы пользуетесь r-shell на компьютере, к которому имеют доступ другие люди, или часто открываете браузер параллельно с работой — смените пароли серверов после обновления. Уязвимость существовала во всех предыдущих версиях, и следов её эксплуатации приложение не сохраняет.

🔒 Зашифрованное хранилище паролей — готово ядро

Пароли пока по-прежнему хранятся открыто, но в этой версии готова вся основа для их шифрования: формат хранилища, шифрование, атомарная запись, парольная фраза, миграция и резолв паролей на стороне Rust. Ключевое решение: команды «выдай пароль» не существует вовсе — даже скомпрометированный интерфейс не сможет их выгрузить. Включение по умолчанию — в следующем релизе.

📦 Установка

macOS (Apple Silicon): скачайте .dmg. Если Gatekeeper ругается:

xattr -dr com.apple.quarantine /Applications/r-shell.app

Linux (x86_64): .AppImage, .deb или .rpm.

Установленная версия обновится сама.

Conchshell 2.8.2 — экспорт настроек больше не выносит пароли открытым текстом

Choose a tag to compare

@github-actions github-actions released this 02 Aug 09:33

🔒 Что нового в 2.8.2 — исправление утечки при экспорте настроек

Экспорт конфигурации больше не записывает пароли в открытый файл.

Раньше «Экспорт настроек» складывал в обычный JSON-файл все учётные данные как есть: пароли подключений, парольные фразы ключей, пароли VNC, прокси и jump-хостов, а из профилей — даже само тело приватного ключа. Такой файл обычно попадает в облачную синхронизацию, Time Machine или общую папку — то есть пароли реально утекали в открытом виде.

Теперь при экспорте все учётные данные вырезаются, а после сохранения приложение честно сообщает, что секреты исключены и их нужно ввести заново после импорта. Импорт не изменился: файл, экспортированный старой версией, по-прежнему импортируется.

⚠️ Что стоит сделать вам

Если вы раньше пользовались экспортом настроек — старые файлы r-shell-config-*.json содержат пароли открытым текстом. Найдите и удалите их (проверьте облако и резервные копии). Помните: удаление файла не стирает его из снапшотов и бэкапов, поэтому самое надёжное — сменить пароли, которые могли попасть в такой экспорт.

Честно о границах

Это исправление закрывает утечку через файл экспорта. Сами пароли в приложении пока по-прежнему хранятся в открытом виде в локальном хранилище — это следующая большая задача. В этом релизе появился документ docs/vault-format.md — готовая к реализации спецификация зашифрованного хранилища учётных данных (один ключ данных, отдельные слоты для прозрачной разблокировки через системную связку ключей и для переносимой парольной фразы Argon2id, атомарный формат файла, защита синхронизации от отката, миграция и честная модель угроз).

📦 Установка

macOS (Apple Silicon): скачай .dmg, перетащи r-shell в Applications. Если Gatekeeper ругается:

xattr -dr com.apple.quarantine /Applications/r-shell.app

Linux (x86_64): .AppImage (сделать исполняемым и запустить), либо .deb / .rpm.

Уже установленная версия подтянет обновление сама через встроенный автоапдейтер.

Conchshell 2.8.1 (macOS + Linux)

Choose a tag to compare

@github-actions github-actions released this 29 Jul 05:15

Исправление к 2.8.0 — все возможности той версии плюс починенный запрос доверия к серверу. Ставить стоит именно эту.

Запрос доверия открывался частью за экраном

В 2.8.0 окно с отпечатком сервера появлялось смещённым вверх: заголовок, адрес и порт оказывались срезаны, а при высоком содержимом прокрутка до них не добиралась. Причин было две, и обе устранены.

Окно центрировалось сдвигом на половину собственной высоты. Пока содержимое ниже экрана, это выглядит как центр; как только выше — верхняя половина уходит за край, и прокрутить к ней нельзя, потому что переполняется не окно, а экран. Теперь центрирование идёт по рамке окна и не зависит от объёма содержимого.

Вторая причина тоньше. Фокус при открытии намеренно ставится на кнопку отказа, чтобы случайное нажатие Enter не подтвердило доверие к незнакомому серверу. Но кнопка находится внизу, и браузер прокручивал к ней содержимое — заголовок с адресом уезжал раньше, чем его можно было прочитать. Теперь фокус ставится без прокрутки.

Обе особенности закреплены тестами: невидимое или прокрученное окно — ровно тот случай, который не заметит ни одна другая проверка.

Conchshell 2.8.0 (macOS + Linux)

Choose a tag to compare

@github-actions github-actions released this 29 Jul 05:04

Проксирование работает по-настоящему

Вкладка «Proxy» в диалоге подключения — с выбором HTTP/SOCKS4/SOCKS5, полями хоста, порта и учётных данных, переведённая на три языка — до сих пор была декорацией: введённые значения никогда не покидали интерфейс, не сохранялись и не доходили до сети. Слово «proxy» не встречалось ни в одной исполняемой строке серверной части.

Теперь поддерживаются SOCKS5, SOCKS4, SOCKS4a и HTTP CONNECT — для SSH, SFTP и RDP одинаково. Это стало возможно потому, что все соединения приложения теперь открываются через один общий транспорт; заодно исчезла третья копия кода подключения, из-за расхождения которых раньше ломалась авторизация SFTP по ключу.

Прямого подключения в обход прокси не бывает. Если прокси настроен, но недоступен — соединение не состоится, и в сообщении будет сказано, что молчит именно прокси, а не сервер. Это принципиально: тихий откат на прямое соединение означал бы, что вы считаете трафик проксированным, когда он идёт напрямую. Протоколы, которые маршрут не поддерживают (FTP, VNC), отказываются, а не игнорируют настройку.

Ошибки называют участок пути: не дозвонились до прокси, прокси отверг учётные данные (и это именно его учётные данные, а не сервера), прокси отказался соединять с целью.

Промежуточный хост для SSH

Появился jump host: вход на промежуточный сервер и оттуда — на целевой. Промежуточный хост проверяется тем же хранилищем отпечатков и под собственным ключом, то есть на одно подключение приходится два независимых решения о доверии. Проверяется он до того, как к целевому серверу уйдут любые учётные данные.

Если заданы и прокси, и промежуточный хост, прокси используется для связи с промежуточным.

Что нашли при проверке

Проверка велась через настоящие прокси-серверы, а не через собственные заглушки, и нашла две вещи, каждая из которых обесценила бы функцию:

  • Библиотека SSH записывает буфер аутентификации в лог до шифрования, поэтому при включённом отладочном логировании пароль и пароль промежуточного хоста попадали в журнал открытым текстом.
  • Неизвестный тип прокси считался отсутствием прокси — то есть подключением напрямую. Сработать это могло от опечатки в импортированном конфиге или от socks4a, который серверная часть умеет, а список интерфейса ещё нет. Теперь это отказ с объяснением.

Тесты: Rust 569, интерфейс 1019.

Conchshell 2.7.0 (macOS + Linux)

Choose a tag to compare

@github-actions github-actions released this 28 Jul 21:54

RDP в отдельном окне

Сессия открывается собственным окном системы, а не только вкладкой. Вкладка остаётся «ручкой» сессии — через неё работают восстановление, статус в дереве подключений и ⌘W. Закрытие окна закрывает сессию; захват клавиатуры следует за окном и не отбирает сочетания у главного.

Перенос файлов по SFTP наконец работает

Три из четырёх способов начать копирование молча ничего не делали:

  • Правый клик по файлу → «Загрузить на сервер» срабатывал только если строку до этого выделили левым кликом: меню читало выделение, а правый клик его не создаёт.
  • Выбор папки и кнопка «→» отваливались до показа уведомления — папки отфильтровывались, и функция выходила молча.
  • Перетаскивание между панелями не работало в принципе: Tauri перехватывает событие раньше страницы. При этом панель подсвечивалась «перетащите сюда», обещая приём. Теперь переписано на pointer-события — тем же способом, каким в приложении уже перетаскиваются вкладки.

Добавлены уведомления об успехе и об ошибке с читаемой причиной: раньше ошибка была видна только обрезанной строкой в свёрнутой панели очереди. Папка в выборке теперь объясняет, что делать, вместо тишины.

Отдельно в клиенте: загрузка не закрывала удалённый файл, поэтому ошибка, которую сервер сообщает при закрытии, отбрасывалась и перенос всегда считался успешным.

Вкладка «Proxy» больше не вводит в заблуждение

Проксирование не реализовано ни для одного протокола — ни SSH, ни SFTP, ни RDP, ни VNC, ни FTP. При этом вкладка с выбором HTTP/SOCKS4/SOCKS5 выглядела рабочей: введённые значения никогда не покидали интерфейс. Поля убраны, на их месте объяснение; значения, сохранённые прошлыми сборками, вычищаются при открытии подключения.

Скорость RDP: что измерено

Весь путь кадра инструментирован на живом хосте. Локальная обработка занимает около 1 мс из ~100 мс задержки «нажал — увидел»: очередь кадров не заполнялась ни разу из 918 отправок, отрисовка кадра — 0.1 мс, транспорт держит 5.8 ГБ/с.

Одна настоящая потеря найдена и убрана: библиотека объединяет все изменившиеся области в один охватывающий прямоугольник, и клиент пересылал его целиком — при перетаскивании окна это давало 52 МБ переданных пикселей на 0.5 МБ реальных изменений.

Остальное — на стороне сервера: он отдаёт картинку 16 битами на пиксель старым RLE-кодеком. Клиент запрашивает 32 бита и объявляет RemoteFX, но при 16 битах RemoteFX не включается. Лечится настройкой ColorDepth в ветке Terminal Server\WinStations\RDP-Tcp на самом хосте.

Прочее

  • Запрос доверия к серверу отрисовывался за пределами экрана и под окном восстановления сессий — восстановление зависало без возможности ответить.
  • CI впервые заработал по-настоящему и сразу поймал два бага, невидимых на машине разработчика: тесты, не собиравшиеся под Linux, и тест, который проходил только потому, что локально выключен sshd.

Тесты: Rust 492, фронтенд 961.

Conchshell 2.6.0 (macOS + Linux)

Choose a tag to compare

@github-actions github-actions released this 28 Jul 18:54

RDP работает по-настоящему

RDP был заглушкой: connect всегда возвращал «не реализовано». Теперь это рабочий клиент на IronRDP — подключение через NLA, поток кадров, клавиатура, мышь, буфер обмена и перенос файлов. Проверено на живом Windows-хосте, а не на моках.

  • Подключение: TCP → X.224 → TLS 1.3 → CredSSP/NTLM → MCS → лицензирование → capability exchange, около 3 секунд.
  • Клавиатура: физические клавиши вместо keyCode, поэтому левый и правый Ctrl больше не путаются, а numpad не сливается со стрелками.
  • Не-ASCII печатается символами, а не позициями клавиш. Скан-код называет позицию, и удалённый хост толкует её своей раскладкой: клавиша «ж» на английской раскладке сервера приезжает как ;. Синхронизировать раскладки — заведомо проигрышная игра, поэтому кириллица уходит Unicode-событиями, и раскладка на той стороне перестаёт иметь значение. Переключать язык в Windows не нужно.
  • Cmd работает как Ctrl. Cmd+C/V/X/A внутри сессии делают то, что вы от них ждёте. Cmd+Q, Cmd+W, Cmd+M и Cmd+H остаются локальными — из полноэкранной сессии всегда есть выход, плюс Cmd+Shift+Esc возвращает клавиатуру принудительно.
  • Буфер обмена в обе стороны и перенос файлов Mac → Windows: копируете в Finder, вставляете в проводнике.

Проверка подлинности серверов

Раньше приложение не проверяло, с кем разговаривает: любой ключ SSH и любой сертификат RDP принимались молча. Соединение шифровалось, но подмена сервера была незаметна.

Теперь при первом подключении показывается отпечаток — в том же формате, что печатает ssh-keygen -lf, так что его можно сверить глазами. При изменении ключа появляется отдельное, более строгое предупреждение.

Чтобы это не превратилось в стену диалогов, ваш ~/.ssh/known_hosts импортируется автоматически. Не импортируются хешированные записи (имя в них необратимо), записи центров сертификации и хосты с противоречивыми ключами — ложная тревога обесценила бы саму тревогу.

Пароль и подпись ключом больше не отправляются непроверенному серверу: решение принимается до аутентификации.

Кириллица в локальном терминале

Приложение, запущенное из Finder, не получает от системы ни одной переменной локали, и оболочка работала в локали C — там кириллица не символы, а байты. Отсюда кракозябры при вставке. Теперь оболочке передаётся ваша локаль.

Прочее

  • SFTP-подключение по ключу не могло работать в принципе: в разбор ключа передавался путь к файлу вместо его содержимого.
  • В лог не попадали никакие предупреждения — фильтр по умолчанию пропускал только ошибки. Из-за этого объяснения отказов вроде «это папка, сожмите её сначала» писались в никуда.
  • Добавлен CI: тесты, проверка типов, паритет локалей.

Тесты: Rust 453, фронтенд 874.

Conchshell 2.5.6 (macOS + Linux)

Choose a tag to compare

@github-actions github-actions released this 27 Jul 17:08

Серверы без интерактивного шелла больше не «висят молча»

Подключение к SFTP-серверу (SFTPGo, internal-sftp с ForceCommand, chroot-джейл) проходило авторизацию, вкладка показывала «подключено» — и терминал оставался пустым. Ни приглашения, ни ошибки.

Причина: create_pty_session уходил в channel.request_pty(...).await без таймаута. Такие серверы канал принимают, а шелл не выдают и на запрос не отвечают — ожидание не заканчивалось никогда.

  • request_pty и request_shell ограничены таймаутом в 10 секунд.
  • Вместо пустого окна терминал печатает понятное объяснение (en/ru/zh-CN): у сервера нет интерактивного шелла, для файлов нужно подключение по протоколу SFTP.
  • Цикл переподключений в этом случае гасится — он структурно бесполезен.

Файловый браузер открывает настоящую домашнюю директорию

Раньше SSH-вкладка всегда стартовала в захардкоженном /home. У chroot-аккаунтов, на macOS (/Users/...), в контейнерах и на BSD такого пути нет — первый листинг падал, и панель выглядела сломанной.

  • Новая команда get_remote_home_dir спрашивает у сервера pwd по exec-каналу (MOTD в выводе не сбивает разбор).
  • Ответ кэшируется на подключение; браузер переходит туда, только если вкладку не переключили и пользователь сам никуда не ушёл.
  • Кнопка «Home» и возврат при исчезнувшем каталоге тоже используют реальный home.

Тесты

Rust 87 passed, фронтенд 488 passed / 7 skipped. i18n-паритет: 944 ключа во всех локалях.