JavaScript que no toca nada que no le dejes.
lumo es un runtime de JavaScript y TypeScript seguro por defecto. Sin flags, el código no puede leer archivos, abrir red, leer variables de entorno ni lanzar procesos. En Linux lo impone también el kernel.
Instala lumo v0.0.1
$ curl -fsSL https://lumo.gitweave.run/install | bashInstala en ~/.lumo/bin sin sudo y verifica el SHA-256 de la descarga. Requiere macOS 14 o posterior con Apple Silicon, o Linux x86_64/arm64 con glibc 2.38 o posterior (Ubuntu 24.04+, Debian 13+, Fedora 39+).
Pide permiso o falla con un mensaje claro
Este programa lee un archivo, una variable de entorno y escribe otro archivo. Concede cada permiso y mira qué cambia en la terminal: el error dice exactamente qué flag falta.
main.js
const config = await Lumo.readTextFile("./config.json");
console.log("config leída");
const token = Lumo.env.get("API_TOKEN");
console.log("token:", token ? "presente" : "ausente");
await Lumo.writeTextFile("./salida.txt", "ok");
console.log("salida escrita");Terminal
$ lumo run main.js
error: Uncaught PermissionDenied: Requiere permiso de lectura de "./config.json"; ejecuta de nuevo con --allow-read=./config.json
código de salida: 1
Simulación con los mensajes reales de lumo. En Linux, además, Landlock bloquearía la lectura aunque el runtime tuviera un bug.
Dos capas, por si una falla
En el runtime, en todas las plataformas
Cada operación con efectos fuera del proceso comprueba su permiso antes de actuar. Las rutas se resuelven antes de comparar, así que ni un .. ni un symlink que apunte fuera de lo concedido abren la puerta.
En el kernel, en Linux
Antes de ejecutar una sola línea de JS, lumo se encierra con Landlock (archivos y puertos TCP) y seccomp (syscalls). Lanzar un proceso sin --allow-run termina con el código 126. No hay forma de pedir más permisos después: se declaran al arrancar.
En macOS solo existe la capa del runtime: el sistema no ofrece un equivalente a Landlock que se pueda usar.
Comparado con otros runtimes
| Característica | lumo | Deno | Bun | Node |
|---|---|---|---|---|
| Motor | JavaScriptCore | V8 | JavaScriptCore | V8 |
| Escrito en | Zig | Rust | Rust | C++ |
| Permisos por defecto | denegados | denegados | sin modelo de permisos | concedidos |
| Confinamiento en el kernel | Landlock y seccomp (Linux) | no | no | no |
| Permisos durante la ejecución | no: se declaran al arrancar | sí, con prompts | — | no |
| Gestor de paquetes | aparte (stil) | integrado | integrado | aparte (npm) |
Dónde está lumo hoy
lumo avanza por hitos y no da uno por cerrado hasta que sus tests pasan en macOS y Linux.
- M1hecho
Motor
JavaScriptCore compilado y enlazado estáticamente; lumo eval.
- M2hecho
Event loop
Timers, microtasks y promesas sobre kqueue, io_uring o epoll.
- M3hecho
Permisos
Flags --allow-*, lumo.json, Landlock y seccomp.
- M4en curso
Módulos y TypeScript
ESM, CommonJS, node_modules y node:path funcionan; falta el borrado de tipos.
- M5pendiente
Red
fetch con TLS y un servidor HTTP con Lumo.serve.
- M6pendiente
Web APIs
URL, Encoding, Streams y Fetch validados con web-platform-tests.
- M7pendiente
Release 0.1
Benchmarks contra Node, Bun y Deno y licencias revisadas. Hoy hay builds de vista previa (0.0.x).