Tema representativo de entrevista

Entrevista de Backend: ¿Cómo implementarías el Permission Model de Node.js?

BackendDifícil
Equipo editorial de Offer.ccPublicado Actualizado

Pregunta

Tu equipo quiere que Node.js restrinja el acceso a archivos, red y procesos secundarios. ¿Cómo evaluarías el límite de seguridad y lo habilitarías de forma segura en producción?

Escenario

Mantienes una API de Node.js en contenedores con dependencias de terceros. Lee configuraciones, accede a almacenamiento de objetos y ocasionalmente lanza un proceso secundario de procesamiento de imágenes. Seguridad propone --permission solo con los permisos requeridos de archivos, red y procesos secundarios. Explica el modelo de amenazas, el inventario de permisos, las pruebas de compatibilidad, el monitoreo y el rollback.

Qué evalúa el entrevistador

  • Saber que el Permission Model es un cinturón de seguridad para código confiable, no un sandbox para código malicioso.
  • Descomponer las capacidades de archivos, red, procesos secundarios, workers y addons nativos bajo el principio de mínimo privilegio.
  • Reconocer enlaces simbólicos, descriptores de archivo existentes, el orden de inicialización y los límites de herencia.
  • Diseñar un canary, telemetría de denegación útil y un rollback seguro para el negocio.

Preguntas aclaratorias

Confirma la versión de Node, el entrypoint, los addons nativos, las necesidades de workers/FFI/WASI, las rutas y dominios, y si la aplicación debe generar procesos. Revisa los controles existentes de contenedor y SO, como seccomp, la identidad del usuario y los sistemas de archivos de solo lectura, para que Node no sea tratado como la única defensa.

Respuesta en 30 segundos

Lo trataría como un control de mínimo privilegio para código confiable, no como una defensa completa contra dependencias maliciosas. Construye concesiones de permisos a partir de auditorías de dependencias y de runtime en producción para fs.read, fs.write, y los ámbitos de red, procesos secundarios y workers. Habilítalo en modo shadow y en el 1% del tráfico, registra ERR_ACCESS_DENIED y la latencia, y prueba addons nativos, enlaces simbólicos y descriptores existentes. Mantén el aislamiento del contenedor. Si la tasa de errores o una dependencia crítica sufre una regresión, elimina el flag de inicio para revertir y perfecciona el inventario.

Razonamiento paso a paso

1. Definir el límite de seguridad

Node describe el Permission Model como una restricción de recursos del proceso y dice explícitamente que no protege contra código malicioso; Node confía en el código que se le pide ejecutar. Reduce el acceso accidental por parte de aplicaciones confiables, pero no puede reemplazar contenedores, usuarios del SO, seccomp o controles en la cadena de suministro de dependencias.

2. Construir el inventario de permisos

Comienza con denegación por defecto. Otorga --allow-fs-read solo a configuraciones y rutas estáticas, limita --allow-fs-write a la salida temporal y --allow-net a los dominios de almacenamiento de objetos requeridos. Agrega --allow-child-process, --allow-worker o --allow-addons solo con una necesidad documentada. Versiona los permisos y exige la revisión del propietario del servicio.

3. Verificar el comportamiento en tiempo de ejecución

Cubre el inicio, health checks, subidas, procesamiento de imágenes, tareas programadas y rutas de error. Verifica process.permission.has() y recuerda que permission.drop() es irreversible y solo afecta las comprobaciones futuras; no cierra descriptores abiertos, sockets ni workers. Prueba enlaces simbólicos, addons nativos, npx y los límites de los procesos secundarios.

4. Canary y rollback

Habilítalo primero en staging y en una instancia sin estado. Recopila la clase del recurso denegado, el stack trace, la versión y el tenant sin registrar valores confidenciales. Condiciona la expansión a la tasa de errores, P95, éxito en el inicio y tareas de negocio completadas. El rollback consiste en eliminar --permission o los flags --allow-* relevantes; conserva los controles de solo lectura, non-root y de red en la capa del contenedor.

Respuesta de ejemplo de alta calidad

Trazaría una matriz de permisos: configuración de solo lectura, un directorio temporal con permisos de escritura, dominios de almacenamiento de objetos requeridos, el proceso secundario de conversión de imágenes y ningún worker ni addon nativo sin un motivo de negocio. El Permission Model restringe fs por defecto, por lo que los parámetros de inicio otorgan cada capacidad explícitamente. Versionaría esos parámetros, ejecutaría escenarios de integración en CI con la imagen más pequeña y verificaría cada ruta y tarea en segundo plano. El canary cubre una clase sin estado, agrega ERR_ACCESS_DENIED y genera hashes de las rutas de recursos. Probaría específicamente enlaces simbólicos, descriptores existentes y el hecho de que los procesos secundarios y workers no heredan el modelo de la misma manera; el riesgo de código malicioso se mitiga con el aislamiento del contenedor y del SO. Expande solo después de que se cumplan los criterios de inicio, P95, denegaciones y finalización de tareas. Si una dependencia crítica es denegada o los errores aumentan, elimina el flag para restaurar el comportamiento y luego actualiza el inventario antes de reintentar.

Errores comunes

  • Afirmar que el Permission Model ejecuta de forma segura paquetes de terceros maliciosos.
  • Otorgar --allow-fs-read=* y --allow-fs-write=* sin necesidad.
  • Ignorar restricciones de addons nativos, workers, procesos secundarios, WASI, FFI o red.
  • Asumir que permission.drop() cierra descriptores, sockets o workers ya abiertos.
  • Probar solo el inicio local y omitir npx, enlaces simbólicos o tareas reales en segundo plano.

Preguntas de seguimiento y respuestas

“¿Puede reemplazar un sandbox de contenedor?”

No. Node indica explícitamente que no protege contra código malicioso. Combínalo con ejecución non-root, sistemas de archivos de solo lectura, seccomp, políticas de red y controles en la cadena de suministro de dependencias.

“¿Por qué el servicio todavía no puede leer un archivo?”

Verifica el entrypoint y la ruta configurada, el comportamiento de los comodines y si las lecturas de inicialización ocurren después de establecer el modelo. Usa permission.has() y eventos de denegación para localizar el permiso faltante.

“¿Cómo permites el procesamiento de imágenes?”

Otorga --allow-child-process por separado, restringe el ejecutable y los directorios de entrada/salida, y mantén las restricciones del SO y del contenedor. Si una llamada a una librería puede reemplazar el proceso secundario, elimina ese permiso en su lugar.

Fuentes públicas

Preguntas relacionadas