Modèle de sécurité : ce que sim fait face à chaque menace

sim est construit autour d’une question : que peut vous faire un fichier, un dossier ou un dépôt que vous n’avez pas écrit ? Cette page présente le modèle de menaces et ce que sim fait face à chaque menace.

Modèle de menaces

Vous ouvrez des fichiers et des dépôts que vous n’avez pas écrits : un clone, une archive décompressée, un checkout de pull request, un fichier écrit par un autre processus. L’attaquant contrôle leur contenu, pas votre machine. sim s’efforce de garantir que ce contenu ne puisse pas se cacher de vous, ne puisse pas reconfigurer l’éditeur et ne puisse pas lui faire exécuter du code.

Hypothèses

  • Vous faites confiance à votre propre terminal, à votre propre compte utilisateur et à votre propre configuration git globale.
  • L’attaquant peut modifier n’importe quel fichier d’un dépôt, y compris .git/config et les fichiers situés à côté de celui que vous ouvrez.
  • L’attaquant ne peut modifier ni sim lui-même, ni votre répertoire personnel.

Menaces et réponse de sim

  • Caractères de contrôle bidirectionnels (Trojan Source)

    La menace

    Des contrôles Unicode réordonnent l’affichage du code, de sorte que le code lu par un relecteur n’est pas celui lu par un compilateur (CVE-2021-42574). Le conseil des chercheurs aux éditeurs de texte est de rendre ces caractères perceptibles.[1] [2] [3]

    Ce que fait sim

    U+200E–200F, U+202A–202E, U+2066–2069 et U+061C sont dessinés sous la forme <U+202E> sur un bloc magenta et ne sont jamais envoyés tels quels au terminal. Le bloc tient dans tous les états où une cellule peut se trouver : sélectionnée, trouvée par une recherche, sur la ligne du curseur, dans une modification venue de l’extérieur, dans le brouillard d’une ligne éloignée, sur un titre ou un bloc de code. Le texte littéral <U+202E> saisi dans un fichier est du texte ordinaire et ne reçoit aucun bloc.

    Spécification: SAFE-8, UI-15

  • Caractères invisibles et espaces

    La menace

    De nombreux caractères Unicode ne dessinent rien du tout. Une suite de caractères de balise, qui reflètent l’ASCII, peut porter une instruction cachée destinée à un assistant d’IA qui lit le fichier (« ASCII smuggling ») ; selon la norme elle-même, un moteur de rendu qui ignore les balises va « display any sequence of tag characters as invisible » (afficher toute suite de caractères de balise comme invisible). Une suite de sélecteurs de variante peut porter un programme : l’un a caché une charge utile dans des extensions VS Code publiées (GlassWorm). Les remplisseurs, les traits d’union conditionnels, les liants et les séparateurs de ligne peuvent se trouver dans un identifiant ou un commentaire sans rien changer de ce que vous voyez. Une espace de largeur nulle, une marque d’ordre des octets au milieu d’un fichier, une espace insécable ou des espaces en fin de ligne changent de la même façon le sens d’un fichier ou la lecture d’un diff.[4] [5] [6] [7] [8] [9]

    Ce que fait sim

    U+200B, et U+FEFF partout sauf au début du fichier, sont dessinés sous la forme <U+200B> et <U+FEFF>. Une espace insécable est dessinée en ⍽, les espaces en fin de ligne en · et les tabulations en ».

    Tout caractère qui ne dessine rien est montré de la même façon, sous la forme <U+E0041> sur le bloc magenta, dans le texte, la ligne d’état, les messages et la ligne de commande, ainsi que dans les noms et les lignes qui viennent de fichiers (l’arborescence, les onglets, le fil d’Ariane et les résultats de recherche) : caractères de format, caractères de balise, sélecteurs de variante, remplisseurs hangul, trait d’union conditionnel, liant de graphèmes combinants, U+2028 et U+2029, et tout point de code qu’Unicode 18.0.0 laisse non attribué. Ceci reste comme c’est : un liant de largeur nulle entre deux émojis, un sélecteur de variante après un pictogramme, les trois drapeaux de l’Angleterre, de l’Écosse et du pays de Galles, et les caractères d’usage privé (les icônes d’une Nerd Font) ; les mêmes caractères ailleurs sont montrés. Le prix : un kanji suivi d’un sélecteur de variante idéographique (une façon enregistrée de choisir une forme de glyphe d’un kanji) montre le sélecteur, 葛<U+E0100>, parce que le même caractère est un canal pour cacher des données ; cela touche surtout le texte japonais. Les recommandations d’Unicode pour les éditeurs de code source conseillent « an option to make visible any default ignorable code points » (une option pour rendre visibles les points de code ignorables par défaut) ; sim n’a pas cette option et les montre toujours.[10] [6] [11] [12] [13]

    Spécification: SAFE-8, SAFE-10, SAFE-11, UI-6

  • Séquences d’échappement du terminal dans les fichiers et les noms de fichiers

    La menace

    Des caractères de contrôle dans un fichier, ou dans un nom de fichier, peuvent atteindre le terminal sous forme de séquences d’échappement.

    Ce que fait sim

    Les caractères C0 et DEL sont dessinés sous la forme ^[ et les C1 sous la forme <U+0085>. Rien de brut n’est écrit dans le terminal, et des tests vérifient les octets envoyés.

    Les caractères de contrôle et bidirectionnels des noms de fichiers sont dessinés sous les mêmes formes, ^[ et <U+202E>, dans l’arborescence, les onglets, le fil d’Ariane, les résultats de recherche et le sélecteur ; la v0.1.0 les dessinait en U+FFFD.

    Spécification: SAFE-8, SAFE-10, TREE-1, GREP-7

  • Réglages cachés dans un fichier (modelines)

    La menace

    Un commentaire dans un fichier peut définir des options de l’éditeur, et des bogues de ce mécanisme ont conduit à l’exécution de code : CVE-2019-12735 (Vim et Neovim) et CVE-2026-34982 (Vim).[14] [15] [16]

    Ce que fait sim

    Les réglages et les commandes ne sont jamais lus dans le contenu d’un fichier. Il n’y a aucune modeline à contourner.

    Spécification: SAFE-9

  • Configuration locale au projet

    La menace

    Un répertoire de projet peut contenir une configuration qu’un éditeur charge et exécute : des fichiers exrc dans Vim et Neovim, .helix/config.toml dans Helix.[17] [18] [19]

    Ce que fait sim

    sim n’a ni fichiers de configuration, ni plugins, ni configuration locale au projet à charger. Seuls vos choix d’apparence, d’icônes et de vue Markdown sont mémorisés, à raison d’un mot chacun, dans le répertoire d’état de sim.

    Spécification: SAFE-9, LOOK-1

  • Configuration de dépôt qui exécute des commandes

    La menace

    git exécute les commandes nommées dans le .git/config du dépôt lui-même. core.fsmonitor désigne un hook que des commandes git comme git status invoquent, et un pilote de filtre désigne des programmes qui s’exécutent sur le contenu d’un fichier. Un éditeur qui demande à git l’état d’un dépôt que vous venez de décompresser peut les exécuter.[20] [21] [22]

    Ce que fait sim

    sim demande d’abord à git la configuration du dépôt. Ce qu’une ligne de commande peut arrêter est désactivé (core.fsmonitor, hooks, filtres, diff externe, conversion de texte), et git répond. Si les portées propres du dépôt définissent autre chose qui peut contenir une commande (core.sshCommand, un include qui pourrait en apporter une), git n’est pas exécuté. Quand il l’est, c’est sans shell, avec --no-optional-locks et dans un environnement qui empêche toute récupération. sim n’exécute aucune commande de git qui écrit, donc aucun hook ne s’exécute. L’arborescence dit n git settings off ou git not run, et la ligne d’état indique la clé et où elle se trouve.

    Spécification: MARK-1, GIT-1, GIT-2, GIT-3, GIT-5

  • Fichiers réécrits de l’extérieur

    La menace

    Une compilation, un formateur ou un outil réécrit le fichier que vous avez ouvert. L’enregistrement écrase alors son travail, ou son travail écrase le vôtre.

    Ce que fait sim

    sim s’en aperçoit, signale ce qui a changé et compare l’empreinte du fichier avec celle prise au chargement, juste avant le renommage. Si elles diffèrent, rien n’est écrit.

    Un changement qui arrive pendant qu’un enregistrement est en cours d’écriture attend désormais la réponse de l’enregistrement, et ne peut donc pas être fusionné sur le texte en train d’être enregistré. Une course rare, trouvée le 2026-10-18, pouvait faire perdre une ligne dans la v0.1.0.

    Spécification: DISK-1, DISK-2, SAFE-5, SAFE-7

  • Plantages et terminaux fermés

    La menace

    Un plantage, un kill -9 ou la fermeture du terminal fait perdre le texte non enregistré.

    Ce que fait sim

    Le texte non enregistré est sauvegardé en instantané au plus une fois par seconde dans un répertoire d’état privé, puis proposé de nouveau sous la forme d’une seule étape d’annulation. Ce répertoire doit être un vrai répertoire, vous appartenir et n’être accessible à personne d’autre ; sinon, les instantanés sont désactivés et sim le signale.

    Spécification: SAFE-6

  • Fichiers qui ne sont pas du texte

    La menace

    Un contenu binaire ou non UTF-8, affiché comme s’il s’agissait de texte, peut cacher ce que contient un fichier et être corrompu par un enregistrement.

    Ce que fait sim

    Ces fichiers s’ouvrent en lecture seule, avec la raison affichée. Les octets invalides sont dessinés en U+FFFD, et toute forme d’écriture est refusée.

    Spécification: SAFE-4

Ce que sim ne fait pas

  • sim n’est pas un bac à sable. Il s’exécute avec vos privilèges. Vous montrer un caractère caché ne vous empêche pas d’exécuter le code qu’il dissimule.
  • Sa liste de caractères est fixe : la table d’Unicode 18.0.0. Un point de code qu’une version ultérieure attribue est montré comme caché jusqu’à ce que la table soit refaite. Ce n’est pas une vérification complète des confusables d’Unicode (UTR #36), et les lettres semblables d’autres écritures (homoglyphes, l’autre moitié de Trojan Source) ne font pas partie de ce que décrit sa documentation.
  • La dernière vérification avant un enregistrement compare l’estampille du fichier, et son empreinte seulement si l’estampille a bougé. Une écriture dans la même microseconde, ou une réécriture de même taille dans un même pas d’horodatage d’un système de fichiers à horodatage grossier, peut encore passer.
  • Tout ce qui figure sur cette page provient de la spécification et des tests du projet lui-même. Aucun audit indépendant n’est cité dans sa documentation.
  • Les serveurs de langage ne sont pas encore pris en charge. Un client dans un bac à sable figure dans la feuille de route ci-dessous.

Feuille de route : serveurs de langage

Prévu

Un serveur de langage est un programme qu’un projet peut demander à votre éditeur de démarrer ; c’est donc l’un des principaux moyens pour un dépôt d’exécuter du code. sim n’en a pas encore. Le plan est un client dans un bac à sable et, dans la ligne d’état, un indicateur signalant si la racine du projet est approuvée. C’est prévu, pas livré.

Sources

  1. NVD: CVE-2021-42574 (bidirectional control characters, “Trojan Source”)
  2. Boucher and Anderson, Trojan Source: Invisible Vulnerabilities (USENIX Security 2023)
  3. Unicode Standard Annex #9: Unicode Bidirectional Algorithm
  4. Unicode Technical Report #36: Unicode Security Considerations
  5. Johann Rehberger, ASCII Smuggler Tool: Crafting Invisible Text and Decoding Hidden Codes (Embrace The Red, 14 January 2024)
  6. Unicode Technical Standard #51: Unicode Emoji, revision 31 (ZWJ sequences, emoji tag sequences, Annex C)
  7. Paul Butler, Smuggling arbitrary data through an emoji (8 February 2025)
  8. 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)
  9. Endor Labs, Invisible Threats and the Blind Spots of Security (an analysis of GlassWorm)
  10. The Unicode Standard 18.0, chapter 23, Special Areas and Format Characters (§23.4 Variation Selectors, §23.9 Tag Characters)
  11. Unicode Technical Standard #55: Unicode Source Code Handling, revision 5 (§4.2 Blank and Invisible Characters)
  12. Unicode Technical Standard #37: Unicode Ideographic Variation Database, revision 16 (ideographic variation sequences)
  13. Unicode Ideographic Variation Database: the registered collections (Adobe-Japan1, Hanyo-Denshi, Moji_Joho and others)
  14. NVD: CVE-2019-12735 (Vim before 8.1.1365 and Neovim before 0.3.6, modeline)
  15. NVD: CVE-2026-34982 (Vim before 9.2.0276, modeline sandbox bypass)
  16. Vim security advisory GHSA-8h6p-m6gr-mpw9 (modeline sandbox bypass)
  17. Vim 9.2.1202, runtime/doc/options.txt ('modeline', 'modelinestrict', 'exrc', 'isprint', 'fsync')
  18. Neovim 0.12.6, runtime/doc/options.txt ('modeline', 'modelineexpr', 'exrc', 'isprint', 'fsync')
  19. Helix 25.07.1, book/src/configuration.md (a config.toml local to a project)
  20. git-config documentation (core.fsmonitor, filter.<driver>.*)
  21. githooks documentation (fsmonitor-watchman, post-index-change)
  22. Justin Steven, Git honours embedded bare repos, and exploitation via core.fsmonitor affects IDEs (2022)
  23. ripgrep user guide (the config file named by RIPGREP_CONFIG_PATH, --pre)