Модель безопасности: что sim делает с каждой угрозой
sim построен вокруг одного вопроса: что файл, папка или репозиторий, которые вы не писали, могут сделать с вами? Эта страница — модель угроз и описание того, что sim делает с каждой угрозой.
Модель угроз
Вы открываете файлы и репозитории, которые не писали: клон, распакованный архив, чекаут pull request, файл, который пишет другой процесс. Атакующий управляет их содержимым, но не вашим компьютером. sim старается сделать так, чтобы это содержимое не могло спрятаться от вас, не могло перенастроить редактор и не могло заставить редактор выполнить код.
Допущения
- Вы доверяете своему терминалу, своей учётной записи и своей глобальной конфигурации git.
- Атакующий может изменить любой файл в репозитории, включая .git/config и файлы рядом с тем, который вы открываете.
- Атакующий не может изменить сам sim или ваш домашний каталог.
Угрозы и что делает sim
Двунаправленные управляющие символы (Trojan Source)
Угроза
Управляющие символы Unicode меняют порядок отображения кода, так что код, который читает рецензент, — не тот код, который читает компилятор (CVE-2021-42574). Исследователи советуют редакторам делать такие символы заметными.[1] [2] [3]
Что делает sim
U+200E–200F, U+202A–202E, U+2066–2069 и U+061C отображаются как
<U+202E>на пурпурном блоке и никогда не отправляются в терминал как есть. Блок сохраняется в любом состоянии ячейки: выделенной, найденной поиском, на строке курсора, внутри изменения извне, в тумане далёкой строки, в заголовке или блоке кода. Буквальный текст<U+202E>, набранный в файле, — обычный текст и блока не получает.Спецификация: SAFE-8, UI-15
Невидимые символы и пробелы
Угроза
Многие символы Unicode вообще ничего не рисуют. Последовательность символов-тегов, повторяющих ASCII, может нести скрытую инструкцию для ИИ-ассистента, читающего файл («ASCII smuggling»); по словам самого стандарта, отрисовщик, не знающий тегов, будет “display any sequence of tag characters as invisible” (показывать любую последовательность символов-тегов как невидимую). Последовательность селекторов вариантов начертания может нести программу: в одном случае так спрятали полезную нагрузку в опубликованных расширениях VS Code (GlassWorm). Заполнители, мягкие переносы, соединители и разделители строк могут стоять внутри идентификатора или комментария, ничего не меняя в том, что вы видите. Пробел нулевой ширины, метка порядка байтов посреди файла, неразрывный пробел или пробелы в конце строки таким же образом меняют смысл файла или то, как читается дифф.[4] [5] [6] [7] [8] [9]
Что делает sim
U+200B и U+FEFF в любом месте, кроме начала файла, отображаются как
<U+200B>и<U+FEFF>. Неразрывный пробел отображается как⍽, пробелы в конце строки — как·, табуляция — как».Любой символ, который ничего не рисует, показывается одинаково — как
<U+E0041>на пурпурном блоке — в тексте, в строке состояния, в сообщениях и в командной строке, а также в названиях и строках, которые приходят из файлов (дерево, вкладки, строка пути и результаты поиска): символы форматирования, символы-теги, селекторы вариантов начертания, хангыльные заполнители, мягкий перенос, объединитель графем, U+2028 и U+2029 и каждый кодовый пункт, который Unicode 18.0.0 оставляет неназначенным. Остаётся как есть: соединитель нулевой ширины между двумя эмодзи, селектор вариантов после пиктограммы, три флага Англии, Шотландии и Уэльса и символы частного использования (значки Nerd Font); те же символы в любом другом месте показываются. Цена: если за иероглифом идёт селектор иероглифического варианта (зарегистрированный способ выбрать одну форму начертания иероглифа), sim показывает селектор,葛<U+E0100>, потому что тот же символ — канал для сокрытия данных; это задевает в основном японский текст. Рекомендации Unicode для редакторов исходного кода советуют “an option to make visible any default ignorable code points” (параметр, делающий видимыми кодовые пункты, игнорируемые по умолчанию); в sim такого параметра нет, он показывает их всегда.[10] [6] [11] [12] [13]Спецификация: SAFE-8, SAFE-10, SAFE-11, UI-6
Управляющие последовательности терминала в файлах и именах файлов
Угроза
Управляющие символы в файле или в имени файла могут дойти до терминала как escape-последовательности.
Что делает sim
Символы C0 и DEL рисуются как
^[, а символы C1 — как<U+0085>. В терминал не пишется ничего «сырого», а тесты проверяют отправленные байты.Управляющие и двунаправленные символы в именах файлов рисуются в тех же формах,
^[и<U+202E>, — в дереве, на вкладках, в строке пути, в результатах поиска и в выборе файлов; v0.1.0 рисовал их как U+FFFD.Спецификация: SAFE-8, SAFE-10, TREE-1, GREP-7
Настройки, спрятанные в файле (строки режима)
Угроза
Комментарий в файле может задавать параметры редактора, а ошибки в этом механизме приводили к выполнению кода: CVE-2019-12735 (Vim и Neovim) и CVE-2026-34982 (Vim).[14] [15] [16]
Что делает sim
Настройки и команды никогда не читаются из содержимого файла. Обходить нечего: строк режима нет.
Спецификация: SAFE-9
Конфигурация внутри проекта
Угроза
Каталог проекта может нести конфигурацию, которую редактор загружает и выполняет: файлы
exrcв Vim и Neovim,.helix/config.tomlв Helix.[17] [18] [19]Что делает sim
В sim нет файлов конфигурации, плагинов и конфигурации проекта, которую можно было бы загрузить. Запоминается только ваш выбор оформления, значков и вида Markdown, по одному слову, в каталоге состояния sim.
Спецификация: SAFE-9, LOOK-1
Конфигурация репозитория, запускающая команды
Угроза
git запускает команды, указанные в собственном
.git/configрепозитория.core.fsmonitorназывает хук, который вызывают такие команды git, какgit status, а драйвер фильтра называет программы, выполняемые над содержимым файла. Редактор, который спрашивает git о статусе только что распакованного репозитория, может их запустить.[20] [21] [22]Что делает sim
Сначала sim спрашивает у git конфигурацию репозитория. Всё, что способна остановить командная строка, отключается (
core.fsmonitor, хуки, фильтры, внешний diff, преобразование текста), и git отвечает. Если собственные области репозитория определяют что-либо ещё, способное содержать команду (core.sshCommand, include, который мог бы её принести), git не запускается. Когда же он запускается, то без оболочки, с--no-optional-locksи в окружении, которое запрещает любую загрузку. sim не запускает ни одной команды git, которая пишет, поэтому ни один хук не срабатывает. Дерево пишетn git settings offилиgit not run, а строка состояния называет ключ и место, где он находится.Спецификация: MARK-1, GIT-1, GIT-2, GIT-3, GIT-5
Поиск, запускающий код репозитория
Угроза
ripgrep берёт дополнительные флаги из файла конфигурации, названного в окружении, и может выполнять команду для каждого читаемого файла (
--pre).[23]Что делает sim
sim находит ripgrep среди абсолютных записей
PATH, запускает его по полному пути, с пустым окружением и--no-config, и никогда не передаёт--pre. Запрос и файлы идут после-eи--, поэтому ни один из них не может стать опцией.Спецификация: GREP-7, GREP-8
Ссылки, ведущие за пределы проекта
Угроза
Символическая ссылка может указывать за пределы проекта, а в общем каталоге может лежать подброшенная ссылка, по которой пойдёт сохранение.
Что делает sim
Поиск и предпросмотр читают только обычные файлы, реальный путь которых находится ниже корня проекта. Сохранение отказывается записывать через ссылку, которая не принадлежит ни вам, ни root, — в любом компоненте пути.
Спецификация: SAFE-1, GREP-7
Файлы, перезаписанные извне
Угроза
Сборка, форматтер или утилита перезаписывает открытый вами файл. Тогда ваше сохранение затирает их работу, или их работа затирает вашу.
Что делает sim
sim замечает это, отмечает изменённое и непосредственно перед переименованием сравнивает хеш файла с хешем при загрузке. Если они различаются, ничего не записывается.
Изменение, пришедшее во время записи сохранения, теперь ждёт ответа сохранения, поэтому его нельзя слить поверх сохраняемого текста. Редкая гонка, найденная 2026-10-18, могла потерять строку в v0.1.0.
Спецификация: DISK-1, DISK-2, SAFE-5, SAFE-7
Сбои и закрытые терминалы
Угроза
Сбой,
kill -9или закрытый терминал приводят к потере несохранённого текста.Что делает sim
Несохранённый текст сохраняется снимками не чаще раза в секунду в приватный каталог состояния и предлагается обратно одним шагом отмены. Каталог должен быть настоящим каталогом, принадлежащим вам и недоступным другим; иначе снимки отключены, и sim сообщает об этом.
Спецификация: SAFE-6
Файлы, не являющиеся текстом
Угроза
Двоичное содержимое или не-UTF-8, показанное как текст, может скрыть, что в файле, и быть испорчено сохранением.
Что делает sim
Такие файлы открываются только для чтения с указанием причины. Некорректные байты рисуются как U+FFFD, а любая запись отклоняется.
Спецификация: SAFE-4
Чего sim не делает
- sim — не песочница. Он работает с вашими правами. Показать вам скрытый символ — не значит помешать вам выполнить код, который этот символ прячет.
- Список символов фиксирован: это таблица Unicode 18.0.0. Кодовый пункт, который назначит более поздняя версия, показывается как скрытый, пока таблицу не построят заново. Это не полная проверка путаемых символов Unicode (UTR #36), а похожие буквы из других письменностей (гомоглифы, вторая половина Trojan Source) не входят в то, что описывает документация.
- Последняя проверка перед сохранением сравнивает штамп файла, а хеш — только если штамп изменился. Запись в ту же микросекунду или перезапись того же размера в пределах одного тика отметки времени на файловой системе с грубыми отметками всё же может проскочить.
- Всё на этой странице основано на собственной спецификации и тестах проекта. Независимого аудита в его документации не приводится.
- Языковые серверы пока не реализованы. Языковой сервер в песочнице есть в дорожной карте ниже.
Дорожная карта: языковые серверы
Запланировано
Языковой сервер — это программа, которую проект может попросить ваш редактор запустить, поэтому это один из самых больших путей, по которым репозиторий может выполнить код. В sim его пока нет. В плане — клиент в песочнице и индикатор в строке состояния: доверен ли корень проекта. Это запланировано, но не выпущено.
Источники
- NVD: CVE-2021-42574 (bidirectional control characters, “Trojan Source”)
- Boucher and Anderson, Trojan Source: Invisible Vulnerabilities (USENIX Security 2023)
- Unicode Standard Annex #9: Unicode Bidirectional Algorithm
- Unicode Technical Report #36: Unicode Security Considerations
- Johann Rehberger, ASCII Smuggler Tool: Crafting Invisible Text and Decoding Hidden Codes (Embrace The Red, 14 January 2024)
- Unicode Technical Standard #51: Unicode Emoji, revision 31 (ZWJ sequences, emoji tag sequences, Annex C)
- Paul Butler, Smuggling arbitrary data through an emoji (8 February 2025)
- Koi Security, GlassWorm: First Self-Propagating Worm Using Invisible Code Hits OpenVSX Marketplace (18 October 2025; the original address now redirects elsewhere, so this is the Internet Archive's copy)
- Endor Labs, Invisible Threats and the Blind Spots of Security (an analysis of GlassWorm)
- The Unicode Standard 18.0, chapter 23, Special Areas and Format Characters (§23.4 Variation Selectors, §23.9 Tag Characters)
- Unicode Technical Standard #55: Unicode Source Code Handling, revision 5 (§4.2 Blank and Invisible Characters)
- Unicode Technical Standard #37: Unicode Ideographic Variation Database, revision 16 (ideographic variation sequences)
- Unicode Ideographic Variation Database: the registered collections (Adobe-Japan1, Hanyo-Denshi, Moji_Joho and others)
- NVD: CVE-2019-12735 (Vim before 8.1.1365 and Neovim before 0.3.6, modeline)
- NVD: CVE-2026-34982 (Vim before 9.2.0276, modeline sandbox bypass)
- Vim security advisory GHSA-8h6p-m6gr-mpw9 (modeline sandbox bypass)
- Vim 9.2.1202, runtime/doc/options.txt ('modeline', 'modelinestrict', 'exrc', 'isprint', 'fsync')
- Neovim 0.12.6, runtime/doc/options.txt ('modeline', 'modelineexpr', 'exrc', 'isprint', 'fsync')
- Helix 25.07.1, book/src/configuration.md (a config.toml local to a project)
- git-config documentation (core.fsmonitor, filter.<driver>.*)
- githooks documentation (fsmonitor-watchman, post-index-change)
- Justin Steven, Git honours embedded bare repos, and exploitation via core.fsmonitor affects IDEs (2022)
- ripgrep user guide (the config file named by RIPGREP_CONFIG_PATH, --pre)