Un sistema tiene que ejecutar un trozo de código que no controlas —un plugin, una dependencia, algo generado— y quieres garantizar que ese código no pueda tocar el sistema de archivos ni lanzar procesos. No que "no deba": que no pueda, mecánicamente. Eso es confinamiento por capabilities, y es uno de los problemas centrales de la seguridad de un runtime.
Diseñarlo y demostrarlo son dos cosas distintas, y confundirlas es caro.
Un diseño es una afirmación
Puedes escribir un documento impecable: "el acceso a fs y a lanzar procesos se controla así, con estos mecanismos, bajo este modelo de amenaza". Es trabajo real y necesario. Pero es una afirmación. Y el modo de fallo de una frontera de seguridad es que parece que aguanta hasta que no aguanta —silencioso, invisible en las pruebas, visible solo cuando alguien la cruza—.
En seguridad, una afirmación no verificada tiene exactamente la forma de una arquitectura preciosa y equivocada. El diseño puede asumir que un gancho del cargador de módulos dispara en un punto donde en realidad no dispara, y todo el razonamiento que cuelga de ahí es correcto y no sirve de nada.
Los mecanismos existen, y son varios
En Node, por nombrar un runtime concreto, hay al menos tres capas, y no son intercambiables:
- El modelo de permisos nativo (
--permission,--allow-fs-read…), que corta el acceso afsy a lanzar procesos a nivel del proceso entero. - SES / Hardened JavaScript (Compartments,
lockdown()), que confina qué puede importar cada módulo dentro del proceso. - La interceptación del cargador de módulos, que controla qué se resuelve cuando el código pide algo.
Elegir bien entre ellas es el diseño. Pero elegir bien no prueba que la elección aguante contra el árbol de dependencias real que vas a correr.
Demostrar en vez de afirmar
La alternativa a firmar un diseño es entregar un arnés de confinamiento: código no confiable que intenta alcanzar la capability peligrosa —abrir un archivo, lanzar un proceso— contra el runtime real y su árbol de dependencias real, y un registro que muestra que cada intento quedó bloqueado. O, si algo se escapa, exactamente dónde.
La diferencia no es cosmética. "Creo que está confinado" y "aquí está la evidencia de que un intento de leer un archivo del sistema desde el plugin devolvió permiso denegado" son afirmaciones de peso muy distinto. La segunda es la disciplina que uso para todo lo demás aplicada a la seguridad: cruzar la frontera del programa y medir lo que sale, no lo que crees que sale.
La parte honesta
Hay una tentación de firmar la frontera desde una autoridad que no has ganado —porque el diseño se ve bien, porque los mecanismos existen—. La disciplina honesta es la contraria: lo que puedes respaldar hoy, lo respaldas; lo que depende de un detalle del runtime que no dominas, no lo afirmas de memoria: lo validas empíricamente, y lo que no se puede demostrar todavía se marca como la costura a co-revisar, no se esconde.
Una frontera demostrada tapa exactamente el hueco que una afirmada deja abierto. Y para quien tiene que confiar en el confinamiento, un arnés que ataca su propia frontera y guarda la evidencia vale más que la palabra del que la diseñó.
Xiliux