Ember is a secure, lightweight code executor built in Rust. It uses AWS Firecracker microVMs to execute untrusted user code (e.g., JavaScript/Node.js) in complete isolation.
Unlike traditional Docker containers, Firecracker provides hardware-level virtualization with sub-second boot times, making it the perfect sandbox for evaluating untrusted code in a highly scalable and secure way.
- True Hardware Isolation: Uses KVM-backed microVMs instead of Linux namespaces (cgroups).
- Sub-second Boot: Boots a full Linux kernel and executes the code almost instantly.
- MicroVM State Management: Automatically configures the VM, sets up a custom
/initscript, handles entropy starvation for V8, and orchestrates the cleanup. - Node.js Environment: Uses a custom-built Alpine Linux rootfs with
nodejsandrng-tools.
This project must be run on a Linux host (e.g., Ubuntu/Debian) because Firecracker requires KVM (Kernel Virtual Machine).
Ensure you have the following dependencies installed:
- Rust & Cargo: Install Rust
- KVM: Hardware virtualization must be enabled in your BIOS.
(Note: You may need to log out and log back in for the
sudo apt update sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils sudo usermod -aG kvm $USERkvmgroup to apply). - Docker: Used exclusively for building the custom Alpine rootfs image.
sudo apt install -y docker.io sudo usermod -aG docker $USER - Filesystem Utilities: Required for creating the code drives.
sudo apt install -y e2fsprogs coreutils
Download the Firecracker binary and place it in your PATH:
wget https://github.com/firecracker-microvm/firecracker/releases/download/v1.7.0/firecracker-v1.7.0-x86_64.tgz
tar -xzf firecracker-v1.7.0-x86_64.tgz
sudo cp release-v1.7.0-x86_64/firecracker-v1.7.0-x86_64 /usr/local/bin/firecrackerCreate a directory to hold the VM assets. By default, the Rust code looks for assets in ~/firecracker/:
mkdir -p ~/firecracker
cd ~/firecrackerDownload the Linux Kernel: We use an uncompressed Linux kernel compatible with Firecracker:
wget https://s3.amazonaws.com/spec.ccfc.min/img/quickstart_guide/x86_64/kernels/vmlinux.bin -O vmlinux-4.14.174Build the Alpine Linux Rootfs:
The default Firecracker rootfs is too minimal to run Node.js. Run the included build script to automatically generate an Alpine rootfs with Node.js and the necessary entropy tools (rngd) installed.
Go to the project repository and run:
./build_rootfs.shThis will use Docker to extract Alpine, install packages via chroot, and generate ~/firecracker/rootfs.ext4.
-
Write the code you want to execute inside the sandbox into a file (e.g.,
index.js).// index.js console.log("Hello from inside the Firecracker microVM!");
-
Run the Rust executor using Cargo. Pass the file you want to execute as an argument:
cargo run --release index.js
- Drive Creation: The executor creates an
ext4drive (/dev/vdb), copies yourindex.jsinto it, and formats it. - Rootfs Patching: It mounts the Alpine rootfs (
/dev/vda) and dynamically patches the/initscript to mount the code drive and execute your code. - VM Boot: Firecracker is spawned. The kernel boots, initializes the
crngusingrngd, and runs the/initscript. - Execution: Your JavaScript is executed by Node.js. Standard output and errors are captured to a file on the code drive.
- Teardown: The VM forces a graceful shutdown via an
i8042keyboard reset, exiting Firecracker cleanly. - Result: The Rust process mounts the code drive one last time, reads the output, prints it to your terminal, and cleans up all temporary resources.
Failed to wait on firecracker: Permission denied/kvmerrors: Make sure your user is part of thekvmgroup and/dev/kvmhas the correct permissions:sudo chown root:kvm /dev/kvm.- Hanging Execution / 120s Timeout:
If the execution hangs, it is likely due to CRNG entropy starvation. Ensure
rng-toolswas successfully installed by thebuild_rootfs.shscript, which provides therngddaemon to pump entropy into the microVM. - Hardcoded Paths:
If you decide to place your
vmlinuxorrootfs.ext4somewhere other than~/firecracker/, you must update thekernel_pathandrootfs_pathvariables located insrc/main.rs.