Seguridad
Cómo OnlineCompiler.io ejecuta de forma segura el código que envían los usuarios
Cada solicitud ejecuta código de alguien que no conocemos. Esta página describe cómo se contiene una ejecución, cómo se protegen las claves y las cuentas, qué almacenamos y qué no afirmamos, para que puedas juzgar si encaja con tu producto.
Por el equipo de OnlineCompiler.io. Actualizado el .
Also in EnglishTambém em português
Cada ejecución tiene su propio sandbox
Una ejecución inicia un contenedor nuevo, ejecuta el programa y elimina el contenedor. Nada se reutiliza entre ejecuciones, así que un programa no puede dejar archivos ni procesos para el siguiente.
- gVisor: los contenedores corren bajo gVisor (runsc), que atiende las llamadas al sistema del programa en un kernel en espacio de usuario, en lugar de pasarlas al kernel del host. No hay alternativa de respaldo: si gVisor no está disponible, la ejecución falla en lugar de arrancar en un runtime menos aislado.
- Sin red: la red está desactivada, así que los programas no pueden llegar a internet, ni a nuestros servidores ni a los tuyos.
- Sin privilegios: los programas corren como un usuario sin privilegios (uid 65534), con todas las capabilities de Linux eliminadas y la escalada de privilegios desactivada.
- Sistema de archivos de solo lectura: la imagen del lenguaje es de solo lectura. El único espacio con escritura es un espacio de trabajo de 256 MB y 128 MB para archivos temporales, ambos en memoria y montados sin setuid ni archivos de dispositivo. El código y el stdin se montan como solo lectura desde un directorio privado creado para esa tarea.
- Límites fijos: 512 MB de memoria sin swap, 2 CPU, 16 procesos, 256 archivos abiertos y sin core dumps. Después de 30 segundos el programa se detiene, y si el contenedor no termina, se cierra a la fuerza.
- Salida acotada: se guardan hasta 64 KB por flujo, y un programa que imprime más de 8 MB se detiene, para que una avalancha de salida no agote nuestros workers.
La lista completa de límites, y los códigos de salida que devuelve una ejecución cuando llega a uno, está en la documentación de la API (en inglés).
¿Basta Docker? Docker, gVisor y microVMs comparados
Por sí solo, no. Las tres formas comunes de aislar un programa se diferencian en quién atiende sus llamadas al sistema y, por lo tanto, en cuánto del kernel del host puede alcanzar un programa hostil:
| Docker (runc) | gVisor (runsc), el que usamos | MicroVM (Firecracker) | |
|---|---|---|---|
| Quién atiende las llamadas al sistema | El kernel del host, filtrado por seccomp | El propio kernel en espacio de usuario de gVisor; solo un conjunto reducido llega al host | Un kernel invitado dentro de una máquina virtual |
| Qué necesita un escape | Un bug del kernel del host al que se pueda llegar con las llamadas permitidas | Un bug en gVisor y luego otro en la interfaz más reducida del host | Un bug en el monitor de máquinas virtuales o en KVM |
| Costo | Ninguno aparte del programa | Los programas que hacen muchas llamadas al sistema corren más lento | Cada sandbox arranca un kernel; el host necesita KVM |
Una microVM traza la línea más firme. gVisor conserva el arranque de un contenedor y deja fuera del alcance del programa la mayor parte del kernel del host, y además cada ejecución aquí corre sin red, sin privilegios y sobre una imagen de solo lectura. El modelo de seguridad de gVisor (en inglés) explica el diseño.
Claves y cuentas
- Dos tipos de clave. Las claves de API llaman a la API REST y al servidor MCP, y van en tu servidor. Las claves de widget están pensadas para páginas públicas: solo funcionan por el WebSocket del widget, no pueden llamar a la API REST y se pueden restringir a tu dominio, lo que comprobamos en cada conexión. Un iframe insertado con una clave restringida solo se puede mostrar en páginas de ese dominio.
- Los límites de la cuenta contienen una clave filtrada. Cada cuenta tiene un límite por minuto (30 ejecuciones por defecto), un tope de ejecuciones pendientes (8), un tope de ejecuciones en un sandbox a la vez (2, para que una cuenta no pueda ocupar todos los sandboxes) y una cuota mensual, compartidos por todas sus claves. Desactiva una clave en el panel para cortarle el acceso.
- Los callbacks solo van a direcciones públicas. El endpoint asíncrono envía los resultados a la URL HTTP o HTTPS de tu clave de API. Se rechazan las direcciones privadas, de loopback y link-local, no se siguen redirecciones, y la dirección se vuelve a comprobar en la entrega, para que un cambio de DNS no pueda apuntarla dentro de nuestra red.
- Cifrado en tránsito. La API y el WebSocket se sirven por HTTPS y WSS; las solicitudes por HTTP sin cifrar se redirigen.
Qué almacenamos
Cada ejecución se guarda como historial de ejecuciones: el código, la entrada, la salida, los errores, el código de salida, los tiempos, la clave que la envió y la dirección IP del cliente. Puedes ver el historial de tu cuenta en el panel. Cuánto tiempo se conserva, y cómo pedir que se borre, está en la Política de Privacidad (en inglés). Los programas en sí no pueden guardar nada: su espacio de trabajo desaparece con el contenedor.
Lo que no afirmamos
- No tenemos certificación SOC 2 ni ISO 27001, y no hemos publicado una auditoría de terceros.
- Ningún sandbox es perfecto. gVisor reduce la parte del kernel que un programa puede alcanzar, y los límites de arriba contienen lo que puede hacer, pero ninguno de los dos es una garantía.
- OnlineCompiler.io solo existe como servicio alojado. Si tu política exige que el código corra en tus propios servidores, no es la opción adecuada.
Cómo reportar una vulnerabilidad
Si encuentras una forma de salir del sandbox, de evadir un límite o de entrar a los datos de otra cuenta, contáctanos con los pasos para reproducirlo antes de divulgarlo públicamente. Haz pruebas solo con tu propia cuenta y no degrades el servicio para otros usuarios.
Preguntas frecuentes
¿Es seguro ejecutar código no confiable con OnlineCompiler.io?
Sí, para eso está hecho. Cada ejecución obtiene un contenedor nuevo bajo gVisor, sin red, con un usuario sin privilegios, un sistema de archivos de solo lectura y límites fijos (512 MB de memoria, 2 CPU, 16 procesos, 30 segundos). El código corre en nuestros servidores, nunca en los tuyos.
¿Basta Docker para ejecutar código no confiable?
Por sí solo, no. Un contenedor Docker común comparte el kernel del host, así que un bug del kernel al que se pueda llegar con las llamadas al sistema que permite puede llevar fuera del contenedor. gVisor pone un kernel en espacio de usuario en medio, y una microVM como Firecracker le da al programa un kernel propio. Ejecutamos todos los programas bajo gVisor.
¿El código en el sandbox puede acceder a internet o a mis servidores?
No. Los contenedores arrancan con la red desactivada, así que los programas no pueden abrir conexiones, descargar paquetes ni conectarse de vuelta a tus sistemas. Los resultados te llegan solo a través de nuestra API.
¿El código de un usuario puede ver el de otro?
Cada ejecución está separada de las demás: obtiene su propio contenedor, con su propio espacio de trabajo en memoria, y su código y su entrada se montan como solo lectura desde un directorio privado para esa tarea. El contenedor se elimina cuando termina la ejecución, así que nada pasa a la siguiente.
¿La clave del widget es secreta?
No. Las claves de widget están en HTML público por diseño. Solo funcionan por el WebSocket que usa el widget, no pueden llamar a la API REST y se pueden restringir a tu dominio. Guarda las claves de la API REST en tu servidor.
¿Guardan el código que se ejecuta?
Sí. Cada ejecución se guarda con su entrada, su salida y sus tiempos como historial de ejecuciones, que puedes ver en tu panel. La Política de Privacidad, en inglés, indica cuánto tiempo se conserva; pídenos borrar tu cuenta y sus datos cuando quieras.