Modelo de seguridad: qué hace sim ante cada amenaza

sim se construye en torno a una pregunta: ¿qué puede hacerle un archivo, una carpeta o un repositorio ajeno a quien lo abre? Esta página es el modelo de amenazas y explica qué hace sim ante cada una.

Modelo de amenazas

Se abren archivos y repositorios que no se han escrito: un clon, un archivo comprimido descomprimido, el checkout de un pull request, un archivo que escribe otro proceso. El atacante controla su contenido, no la máquina del usuario. sim procura que ese contenido no pueda ocultarse, no pueda reconfigurar el editor y no pueda hacer que el editor ejecute código.

Supuestos

  • Se confía en la propia terminal, en la propia cuenta de usuario y en la configuración global de git.
  • El atacante puede modificar cualquier archivo de un repositorio, incluidos .git/config y los archivos que están junto al que se abre.
  • El atacante no puede modificar el propio sim ni el directorio personal del usuario.

Amenazas y qué hace sim

  • Caracteres de control bidireccionales (Trojan Source)

    La amenaza

    Los controles de Unicode reordenan cómo se muestra el código, de modo que el código que lee un revisor no es el que lee un compilador (CVE-2021-42574). El consejo de los investigadores a los editores es hacer perceptibles estos caracteres.[1] [2] [3]

    Qué hace sim

    U+200E–200F, U+202A–202E, U+2066–2069 y U+061C se dibujan como <U+202E> sobre un bloque magenta y nunca se envían en bruto a la terminal. El bloque se mantiene en cualquier estado en que pueda estar una celda: seleccionada, coincidente con una búsqueda, en la línea del cursor, dentro de un cambio externo, en la niebla de una fila lejana, en un título o en un bloque de código. El texto literal <U+202E> escrito en un archivo es texto normal y no recibe bloque.

    Especificación: SAFE-8, UI-15

  • Caracteres invisibles y espacios

    La amenaza

    Muchos caracteres Unicode no dibujan nada. Una serie de caracteres de etiqueta, que reflejan ASCII, puede llevar una instrucción oculta para un asistente de IA que lee el archivo («ASCII smuggling»); según el propio estándar, un renderizador que ignora las etiquetas “display any sequence of tag characters as invisible” (muestra cualquier secuencia de caracteres de etiqueta como invisible). Una serie de selectores de variación puede llevar un programa: uno escondió una carga útil en extensiones de VS Code publicadas (GlassWorm). Los rellenos, los guiones suaves, los unidores y los separadores de línea pueden estar dentro de un identificador o de un comentario sin cambiar nada de lo que ves. Un espacio de ancho cero, una marca de orden de bytes en medio de un archivo, un espacio de no separación o los espacios finales cambian lo que significa un archivo, o cómo se lee un diff, de la misma manera.[4] [5] [6] [7] [8] [9]

    Qué hace sim

    U+200B, y U+FEFF en cualquier lugar salvo el inicio del archivo, se dibujan como <U+200B> y <U+FEFF>. Un espacio de no separación se dibuja como ⍽, los espacios finales como · y los tabuladores como ».

    Todo carácter que no se dibuja se muestra del mismo modo, como <U+E0041> sobre el bloque magenta, en el texto, la línea de estado, los mensajes y la línea de comandos, y en los nombres y líneas que vienen de archivos (el árbol, las pestañas, la ruta de navegación y los resultados de búsqueda): caracteres de formato, caracteres de etiqueta, selectores de variación, rellenos hangul, el guion suave, el unidor de grafemas combinantes, U+2028 y U+2029, y todo punto de código que Unicode 18.0.0 deja sin asignar. Esto se queda como está: un unidor de ancho cero entre dos emoji, un selector de variación tras un pictograma, las tres banderas de Inglaterra, Escocia y Gales y los caracteres de uso privado (los iconos de una Nerd Font); los mismos caracteres en cualquier otro sitio se muestran. El precio: un kanji seguido de un selector de variación ideográfica (una forma registrada de elegir una forma de glifo de un kanji) muestra el selector, 葛<U+E0100>, porque el mismo carácter es un canal para esconder datos; esto recae sobre todo en el texto japonés. La guía de Unicode para editores de código fuente recomienda “an option to make visible any default ignorable code points” (una opción para hacer visibles los puntos de código ignorables por defecto); sim no tiene esa opción y los muestra siempre.[10] [6] [11] [12] [13]

    Especificación: SAFE-8, SAFE-10, SAFE-11, UI-6

  • Secuencias de escape de terminal en archivos y nombres de archivo

    La amenaza

    Los caracteres de control de un archivo, o de un nombre de archivo, pueden llegar a la terminal como secuencias de escape.

    Qué hace sim

    Los caracteres C0 y DEL se dibujan como ^[ y los C1 como <U+0085>. Nada en bruto se escribe en el terminal, y las pruebas comprueban los bytes enviados.

    Los caracteres de control y bidireccionales de los nombres de archivo se dibujan con las mismas formas, ^[ y <U+202E>, en el árbol, las pestañas, la ruta de navegación, los resultados de búsqueda y el selector; la v0.1.0 los dibujaba como U+FFFD.

    Especificación: SAFE-8, SAFE-10, TREE-1, GREP-7

  • Ajustes ocultos en un archivo (modelines)

    La amenaza

    Un comentario de un archivo puede establecer opciones del editor, y errores en ese mecanismo han llevado a la ejecución de código: CVE-2019-12735 (Vim y Neovim) y CVE-2026-34982 (Vim).[14] [15] [16]

    Qué hace sim

    Los ajustes y comandos nunca se leen del contenido de un archivo. No hay ninguna modeline que eludir.

    Especificación: SAFE-9

  • Configuración local del proyecto

    La amenaza

    Un directorio de proyecto puede contener configuración que un editor carga y ejecuta: archivos exrc en Vim y Neovim, .helix/config.toml en Helix.[17] [18] [19]

    Qué hace sim

    sim no tiene archivos de configuración, ni plugins, ni configuración local de proyecto que cargar. Solo se recuerdan la apariencia, el icono y la vista de Markdown elegidos, una palabra cada uno, en el directorio de estado de sim.

    Especificación: SAFE-9, LOOK-1

  • Configuración de repositorio que ejecuta comandos

    La amenaza

    git ejecuta comandos indicados en el .git/config del propio repositorio. core.fsmonitor nombra un hook que invocan comandos de git como git status, y un controlador de filtro nombra programas que se ejecutan sobre el contenido de un archivo. Un editor que pide a git el estado de un repositorio recién descomprimido puede ejecutarlos.[20] [21] [22]

    Qué hace sim

    sim primero le pide a git la configuración del repositorio. Lo que una línea de comandos puede detener se desactiva (core.fsmonitor, los hooks, los filtros, un diff externo, una conversión de texto) y git responde. Si los ámbitos propios del repositorio definen cualquier otra cosa que pueda contener un comando (core.sshCommand, un include que podría traer uno), no se ejecuta git. Cuando se ejecuta, es sin shell, con --no-optional-locks y con un entorno que impide cualquier descarga. sim no ejecuta ningún comando de git que escriba, así que ningún hook se ejecuta. El árbol dice n git settings off o git not run, y la línea de estado indica la clave y dónde está.

    Especificación: MARK-1, GIT-1, GIT-2, GIT-3, GIT-5

  • Archivos reescritos desde fuera

    La amenaza

    Una compilación, un formateador o una herramienta reescribe el archivo abierto. Entonces el guardado pisa su trabajo, o su trabajo pisa el propio.

    Qué hace sim

    sim lo detecta, marca lo que cambió y compara el hash del archivo con el de la carga justo antes del renombrado. Si difieren, no se escribe nada.

    Un cambio que llega mientras se escribe un guardado ahora espera la respuesta del guardado, así que no puede fusionarse sobre el texto que se está guardando. Una carrera poco frecuente, encontrada el 2026-10-18, podía perder una línea en la v0.1.0.

    Especificación: DISK-1, DISK-2, SAFE-5, SAFE-7

  • Fallos y terminales cerradas

    La amenaza

    Un fallo, kill -9 o una terminal cerrada hacen perder el texto sin guardar.

    Qué hace sim

    El texto sin guardar se captura en una instantánea como máximo una vez por segundo en un directorio de estado privado y se ofrece de nuevo como un solo paso de deshacer. El directorio debe ser un directorio real, propiedad del usuario y sin acceso para otros; de lo contrario, las instantáneas se desactivan y sim lo indica.

    Especificación: SAFE-6

  • Archivos que no son texto

    La amenaza

    El contenido binario o que no es UTF-8, mostrado como si fuera texto, puede ocultar lo que contiene un archivo y corromperse al guardar.

    Qué hace sim

    Estos archivos se abren en solo lectura con el motivo a la vista. Los bytes no válidos se dibujan como U+FFFD y se rechaza cualquier tipo de escritura.

    Especificación: SAFE-4

Lo que sim no hace

  • sim no es un sandbox. Se ejecuta con los privilegios del usuario. Mostrar un carácter oculto no impide ejecutar el código que ese carácter oculta.
  • Su lista de caracteres es fija: la tabla de Unicode 18.0.0. Un punto de código que una versión posterior asigne se muestra como oculto hasta que se rehaga la tabla. No es una comprobación completa de los confusables de Unicode (UTR #36), y las letras parecidas de otras escrituras (homoglifos, la otra mitad de Trojan Source) no forman parte de lo que describe su documentación.
  • La última comprobación antes de guardar compara la marca del archivo y su hash solo si la marca cambió. Una escritura en el mismo microsegundo, o una reescritura del mismo tamaño dentro de un tic de marca de tiempo en un sistema de archivos de marcas gruesas, aún puede colarse.
  • Todo lo que figura en esta página procede de la especificación y las pruebas del propio proyecto. Su documentación no cita ninguna auditoría independiente.
  • Todavía no hay servidores de lenguaje. En la hoja de ruta de abajo figura uno que se ejecuta en un sandbox.

Hoja de ruta: servidores de lenguaje

Previsto

Un servidor de lenguaje es un programa que un proyecto puede pedir al editor que inicie, por lo que es una de las principales vías por las que un repositorio puede ejecutar código. sim todavía no tiene uno. El plan es un cliente en un sandbox y un indicador en la línea de estado de si se confía en la raíz del proyecto. Está previsto, no publicado.

Fuentes

  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)