herkos
Compile-time memory isolation via WebAssembly-to-Rust transpilation.
herkos transpiles WebAssembly modules into safe Rust code, offering type-system-enforced isolation as a lightweight alternative to hardware-based memory protection (MMU/MPU). When hardware isolation is overkill or simply unavailable, herkos lets the Rust compiler enforce the guarantees instead: no MMU, no context switches, no runtime overhead for proven accesses.
Status: Work in progress. Not all Wasm features or corner cases are covered. Do not use in production.
The idea
Running untrusted or unsafe-language code usually requires hardware isolation (processes, hypervisors, MMU/MPU). That's the right tool for many jobs — but sometimes it's overkill: a small plugin, a single C library, a microcontroller with no MMU. For those cases, herkos offers a lighter-weight approach: transpile Wasm to safe Rust, so the compiler itself enforces spatial isolation.
Compile-Time Isolation
┌────────────────────────────────────┐
C / C++ / Rust ──────▶ │ .wasm ──herkos──▶ Safe Rust │ ──rustc──▶ Binary
(unsafe code) clang/ │ (no unsafe) │ (isolated)
rustc └────────────────────────────────────┘
This enables:
- Sandboxing C/C++ libraries without hardware protection: isolate a JPEG decoder, a crypto library, or a plugin system
- Porting unsafe code to Rust: use Wasm as an IR to get a safe Rust version of existing C/C++ code
- Bare-metal isolation:
#![no_std], no heap, no OS required. Run isolated components on microcontrollers
Example: C to safe Rust in 3 steps
1. Write C code (or any language that compiles to Wasm):
int
2. Compile to Wasm, then transpile:
3. Use from Rust — every call returns Result, traps become errors:
The generated fibonacci.rs contains no unsafe, no function pointers, no heap allocations. Memory access is bounds-checked, division by zero returns Err(WasmTrap::DivisionByZero), and the module's memory is structurally isolated from the rest of your program.
See the full C-to-Wasm-to-Rust example.
How it works
.wasm ─▶ Parser ─▶ IR Builder ─▶ Optimizer ─▶ Backend ─▶ Codegen ─▶ rustfmt ─▶ output.rs
wasmparser SSA-form dead block safe Rust
IR elimination backend source
The transpiler parses a .wasm binary, builds an SSA-form intermediate representation, optimizes it, and emits Rust source code through a safe backend. The output depends only on the herkos-runtime crate.
Generated code structure
Each Wasm module becomes a Rust struct that owns its isolated memory:
;
- Memory —
IsolatedMemory<MAX_PAGES>: a fixed-size 2D array, fully stack/BSS allocated, no heap. Every load/store is bounds-checked - Imports — become trait bounds:
fn send<H: SocketOps>(host: &mut H, ...). No imports = no host parameter - Exports — become methods on the module struct
- Indirect calls — safe
matchdispatch over function indices. No function pointers, no vtables - Errors —
WasmResult<T> = Result<T, WasmTrap>. No panics, no unwinding
Security properties
| Property | How |
|---|---|
| No buffer overflows | Every memory access is bounds-checked against active_pages * PAGE_SIZE |
| No cross-module access | Each module owns a distinct IsolatedMemory; the type system prevents cross-access |
| No unauthorized syscalls | Imports are trait bounds — you can't call socket_open unless the host implements SocketOps |
| No ROP gadgets | No function pointers in generated code; indirect calls use static match dispatch |
| No panics | All errors are Result<T, WasmTrap>; no unwinding |
Quick start
Install
Or from source:
Transpile
Use from build.rs (compile-time pipeline)
let wasm_bytes = read.unwrap;
let rust_code = transpile.unwrap;
write.unwrap;
Project structure
| Crate | Purpose | no_std |
|---|---|---|
herkos |
CLI transpiler: .wasm binary in, Rust source out |
No |
herkos-runtime |
Runtime library shipped with transpiled output | Yes |
herkos-tests |
Integration tests + benchmarks | No |
Build and test
Documentation
- Requirements — formal requirements (REQ_* IDs)
- Specification — architecture, transpilation rules, memory model, security analysis
- Future work — verified backend, hybrid backend, temporal isolation
License
Licensed under the Apache License, Version 2.0 (LICENSE).