11 puntos por GN⁺ 2025-09-20 | 1 comentarios | Compartir por WhatsApp
  • Los ataques a la cadena de suministro consisten en que actualizaciones maliciosas se infiltran en el código open source, y Obsidian usa una estrategia de reducir las dependencias externas en sí para minimizarlos
  • Implementa internamente la mayor parte de las funciones de la app o, cuando hace falta, incluye y administra código bifurcado (forkeado) dentro de su propia base de código
  • Las bibliotecas grandes indispensables (pdf.js, Mermaid, MathJax, etc.) se aseguran mediante fijación de versión, y las actualizaciones solo se realizan con cuidado cuando hay parches de seguridad
  • Todas las dependencias se fijan con un lockfile, y no se ejecutan scripts postinstall, lo que bloquea la ejecución de código arbitrario durante la instalación
  • Mediante este procedimiento de actualización cauteloso y estrategia de retraso temporal, Obsidian puede responder antes de que amenazas potenciales sean detectadas por la comunidad

Qué es un ataque a la cadena de suministro

  • Un ataque a la cadena de suministro es una forma en la que actualizaciones maliciosas se infiltran en el código distribuido dentro del ecosistema open source
  • Como muchas apps usan código open source, una sola actualización maliciosa puede afectar en cascada a múltiples aplicaciones
  • Obsidian reduce esta superficie de ataque mediante una estrategia de minimizar dependencias, y diseña la app con la seguridad en mente

Estrategia de minimización de dependencias: Less is Safer

  • Obsidian depende de muy pocas bibliotecas externas en comparación con otras apps de su categoría
  • Las funciones principales (por ejemplo, Bases y Canvas) se implementan internamente en lugar de incorporar bibliotecas externas
    • Esto permite mantener control total sobre el código que se ejecuta
  • Las funciones utilitarias pequeñas casi siempre son implementadas directamente por el equipo de desarrollo
  • Los módulos de tamaño intermedio se forkean e integran en la base de código cuando la licencia lo permite
  • Las bibliotecas grandes (pdf.js, Mermaid, MathJax, etc.) se incluyen con versiones verificadas y fijadas, y solo se actualizan de forma mínima cuando se detectan problemas de seguridad importantes
  • Todos los cambios externos se revisan en detalle y se someten a procedimientos de prueba rigurosos
  • De esta manera también se minimiza la cantidad de subdependencias, reduciendo desde el inicio el riesgo primario de que entre código malicioso

Qué se incluye realmente en la app

  • En la app que realmente ejecuta el usuario solo se incluyen muy pocos paquetes, como Electron, CodeMirror y moment.js
  • Las demás herramientas de desarrollo se usan solo durante el proceso de build de la app y no se entregan al usuario final

Fijación de versiones y manejo del lockfile

  • Todas las dependencias externas se gestionan mediante fijación estricta de versión (pin) y commits del lockfile
  • Esto hace que la instalación sea siempre reproducible y facilita el seguimiento de cambios
  • Con la política de no ejecutar scripts postinstall, se bloquea de raíz la posibilidad de ejecutar código arbitrario durante la instalación

Un proceso de actualización lento y cuidadoso

  • Cuando hace falta actualizar dependencias, se sigue un proceso de revisión sistemática como el siguiente
    • Revisión minuciosa, línea por línea, del changelog
    • Verificación de las dependencias secundarias agregadas en la nueva versión
    • Si el cambio es grande o hay factores de riesgo, revisión directa del diff contra el código upstream
    • Ejecución de pruebas automáticas y manuales en rutas y plataformas principales
    • Solo después de pasar todas estas etapas se hace el commit del lockfile
  • Como la mayoría de las dependencias no necesita cambios frecuentes, la frecuencia de actualización en sí es baja
  • La incorporación de nuevo código externo se revisa y administra con el mismo nivel de exigencia que adoptar una nueva dependencia

“Tiempo de margen” para la estabilidad: Time is a buffer

  • Las distintas actualizaciones no se despliegan de inmediato, sino que se retrasan durante un tiempo determinado
  • Durante ese período, la comunidad open source y los investigadores de seguridad pueden detectar versiones maliciosas, lo que funciona como una ventana de respuesta anticipada
  • Para cuando llega el momento del despliegue real, es más probable que cualquier problema ya haya sido identificado, lo que ayuda a minimizar el riesgo

Conclusión

  • Ninguna medida de seguridad por sí sola puede eliminar por completo el riesgo de ataques a la cadena de suministro
  • Sin embargo, Obsidian reduce de forma importante ese riesgo al combinar minimización de dependencias, grafo poco profundo, fijación de versiones, prohibición de postinstall y actualizaciones lentas centradas en revisión
  • Estos procedimientos también amplían significativamente el tiempo disponible para detectar riesgos antes de que el código llegue al usuario
  • El enfoque completo de seguridad de Obsidian y el historial de auditorías de seguridad anteriores pueden consultarse en su security page oficial

1 comentarios

 
GN⁺ 2025-09-20
Opiniones en Hacker News
  • Muchos comentarios pasan por alto que la mayoría de los usuarios de Obsidian usan plugins comunitarios de terceros; en la práctica, el modelo de seguridad de plugins de Obsidian es muy débil, ya que los plugins tienen acceso a todos los archivos dentro del vault. Si Obsidian hubiera hecho más esfuerzo por integrar directamente más funciones, el riesgo de seguridad sería menor. También podría mejorarse con una estructura como la de las extensiones de navegador, donde se declaren los permisos que usa cada plugin y se bloquee el acceso a permisos no autorizados. Todo eso brindaría una seguridad real al usuario mucho mayor que la lógica de “depender menos de terceros”.

    • Antes se hablaba a veces de casos en los que ideas del diseño de videojuegos terminaban influyendo en otro software más general, pero ya casi no se escucha eso. Sería de gran ayuda para todo el ecosistema de software que personas clave de viejas compañías de videojuegos como Blizzard escribieran un libro detallando cómo funcionó durante la primera década el sistema de plugins de World of Warcraft, qué problemas tuvo y cómo se fue reforzando su seguridad. Muchos sistemas de plugins en distintos proyectos son una mezcla de fragilidad e improvisación.

    • Los plugins de Obsidian no solo pueden acceder a los archivos del vault, sino a todos los archivos de la computadora. Ya señalé esto antes en Discord, pero me ignoraron.

    • Lo veo parecido a Arch Linux: incluso para ingenieros es difícil manejar la seguridad cuando administran software directamente desde AUR; esperar que usuarios comunes carguen con esa responsabilidad es demasiado.

    • Creo que tarde o temprano saldrá a la luz algún caso de filtración de datos provocado por un plugin de Obsidian, y recién entonces el equipo introducirá medidas de seguridad. Como mínimo, hace falta un sistema de publicadores verificados.

    • Desarrollo plugins comerciales para Obsidian, y me gustaría que existiera un proceso de revisión de mayor nivel para plugins que superen cierto umbral de complejidad. Operar dos repositorios, como en Arch Linux con AUR por un lado y otro con revisión más estricta, ayudaría tanto a mejorar la velocidad de revisión como la seguridad.

  • Hay una explicación que dice que “un ataque a la cadena de suministro es cuando una actualización maliciosa se cuela en código abierto usado por muchas apps”, pero cualquier código fuente, no solo el open source (FOSS), puede ser objetivo de ataques. Es problemático instalar la idea de que FOSS es necesariamente más vulnerable.

  • La política de “no ejecutar scripts postinstall durante la instalación” tiene una buena intención, pero si el paquete ya está comprometido, omitir postinstall no vuelve seguro al resto del código. Si el paquete es legítimo, postinstall también puede ayudar a una instalación válida. Como en la práctica muchos incidentes ocurren más por parches de vulnerabilidades comunes que por ataques de cadena de suministro, bloquear actualizaciones podría incluso aumentar el riesgo.

    • Hoy en día el escaneo de seguridad suele hacerse después de la instalación (post install). Conviene impedir que se ejecute cualquier cosa durante la instalación. Ojalá en el futuro haya más funciones para escanear o restringir en la etapa de instalación; algunos productos comerciales ya lo soportan, pero no es algo generalizado.

    • Aun así, sí sirve para proteger la máquina de compilación, porque no tienes que preocuparte de que scripts arbitrarios se ejecuten desde tus innumerables dependencias.

  • La responsabilidad por todo el código distribuido a los usuarios recae en el desarrollador; si no fijas las dependencias, es como “descargar código aleatorio de internet y confiar en la suerte”.

    • Si fijas las dependencias, luego puedes perderte parches de seguridad; eso también es riesgoso, así que es indispensable tener un sistema para enterarte cuando salen nuevos parches de seguridad. Luego hay que hacer backport del parche o actualizar a una versión nueva.

    • Incluso las dependencias fijadas incluyen a su vez otras dependencias, así que al final siempre estás en una estructura de “descargar código aleatorio y esperar lo mejor”, sobre todo en apps basadas en Electron, donde viene una cantidad absurda de código.

  • Últimamente he visto con frecuencia el consejo de no actualizar dependencias aunque salga un patch release, y no lo entiendo. Tal vez al no actualizar se reduzca el riesgo de instalar malware, pero por lo general los parches existen para mejorar la seguridad. Me pregunto si realmente es sensato no aplicar los parches más recientes.

    • La clave es entender por qué aplicas un parche y qué cambió. Como no hay tiempo para leer todo el código fuente, uso herramientas y servicios importantes como Npm Audit para revisar resúmenes de vulnerabilidades. Yo sigo una estrategia de postergar actualizaciones salvo que sean realmente necesarias, porque las actualizaciones también son un vector de ataque y una fuente importante de bugs. Aun así, reviso periódicamente a qué vulnerabilidades estoy expuesto. Si se trata de una vulnerabilidad en una función que ni uso, a veces retraso la actualización; solo actualizo de inmediato fallas realmente críticas. La seguridad es un proceso activo y continuo, y la respuesta debe variar según la tolerancia al riesgo de cada organización. La respuesta no es simplemente “actualiza siempre” o “nunca actualices”.

    • Últimamente, cada vez que actualizo Z-WaveJS UI vuelven a aparecer actualizaciones de dependencias. Ese patrón tan poco satisfactorio me hace revisarlo manualmente. Hoy todos dependemos de dependencias, así que “no tiene fin”; con una sola actualización automática ya te expones.

    • Al actualizar siempre existe el riesgo de mejorar o empeorar, y en el ecosistema npm (donde cae Obsidian) ese riesgo es mucho mayor. En npm hace falta intervención humana para remover paquetes maliciosos, así que la respuesta es lenta. Retrasar deliberadamente algunas actualizaciones al menos da cierto margen defensivo.

    • Últimamente la tendencia es esperar un poco después de un patch release antes de instalarlo. Hoy en día muchos incidentes se detectan en cuestión de horas; varias empresas monitorean npm y hasta hacen negocio de seguridad con ello. En pnpm se puede configurar para instalar solo paquetes publicados hace más de X minutos; yo suelo esperar al menos 24 horas. Configuración minimumreleaseage de pnpm

    • Hace dos semanas, el ataque que recibió mi paquete apuntó justamente a un patch release. No fue un script postinstall. El escaneo automatizado lo detecta rápido, así que este problema ya no destaca tanto. Cuando se descubre una vulnerabilidad en un paquete, llega una alerta de inmediato y queda muy claro. Usar version ranges es de lo peor para responder a ataques de cadena de suministro.

  • Me cuesta estar de acuerdo con la afirmación de que el paquete no es grande porque solo incluye Electron, CodeMirror y moment.js. Electron es software basado en webviews con una complejidad enorme, y para moment.js ya existen APIs mejores. El nivel de manejo de dependencias de Obsidian me parece más bien un estándar mínimo, no una política de seguridad especialmente impresionante. Aun así, es positivo que hagan auditorías de seguridad periódicas.

  • He usado otras apps además de Obsidian, pero Obsidian también me está empezando a interesar. El hecho de que sea una app Electron hace que consuma muchos recursos y, al no ser nativa, JavaScript siempre me da cierta desconfianza. Me pregunto si ya me quedé con una sensibilidad demasiado antigua.

    • JavaScript es un lenguaje muy seguro. Los navegadores web son un ejemplo exitoso de ejecución segura de JavaScript a escala mundial: cada sitio web no puede leer los datos de los demás. Electron también ejecuta JavaScript en sandbox con el motor v8. Mientras evites ejecutar código proveniente de la entrada del usuario, es bastante seguro. El problema de los ataques de cadena de suministro es de npm en sí, no del lenguaje JS. npm tiene la responsabilidad de aplicar políticas de seguridad más estrictas al publicar paquetes.

    • JavaScript es, por casi cualquier medida, uno de los lenguajes más usados del mundo. Corre en casi todas las computadoras y smartphones; por eso mismo se descubren problemas de seguridad con mayor frecuencia. No hay base para asumir que una app nativa sea más segura.

    • Que una app sea Electron no es un problema en sí. GitHub, VS Code, Slack, Discord y Postman también están basados en Electron. A mí me dan ganas de preguntar: ¿qué trabajo tan exigente haces realmente en una app de notas Markdown como para que el rendimiento sea un problema? Casi dan ganas de pensar si la usas en una laptop antiquísima viendo todo en texto plano con el navegador Lynx.

    • Electron no me gusta mucho (por eso prefiero tauri), pero aun así Obsidian en sí es excelente y no hay que descartarlo por culpa de Electron. También lo recomiendo porque se integra con MCP y sirve muy bien como base de conocimiento personal.

    • Electron sí es pesado. En PC no suele ser un gran problema, pero en móvil, cuando acumulas miles de notas, el arranque de la app se vuelve lento incluso sin plugins. Los usuarios lo esquivan con plugins o apps para captura rápida, pero ojalá existiera un Obsidian nativo más liviano.

  • Obsidian está basado en Electron y, por su naturaleza, arrastra peso y cierto riesgo de vulnerabilidades de seguridad.

    • Pero a cambio ofrece la misma UX en todas las plataformas y un nivel de accesibilidad comparable al nativo.
  • Uso Emacs y Org-Roam, y lo ejecuto dentro de una VM sin conexión de red (un Qube de Qubes OS). No puedo revisar personalmente todo el código que corre dentro de Emacs.

  • Si quieres una app nativa y reducir aún más el riesgo de cadena de suministro, una alternativa es Zim Wiki, basada en GTK y empaquetada en las principales distribuciones de Linux. Ir a Zim Wiki

    • Zim Wiki no tiene app móvil nativa ni funciones de sincronización, y por eso me atrae más Obsidian. Mientras no instales plugins al azar, en seguridad está bastante bien.