Aegis
Run untrusted WebAssembly code safely
Installation | CLI Usage | Library Usage | Features
What is Aegis?
Aegis is a WebAssembly sandbox that lets you run untrusted code without risk. The code:
- Cannot access your filesystem (unless you allow it)
- Cannot access the network (unless you allow it)
- Cannot use unlimited memory (you set the limit)
- Cannot run forever (you set the timeout)
- Cannot crash your application
Use cases: Plugin systems, serverless functions, game mods, user-submitted code, CI/CD isolation, safe scripting.
Installation
CLI Tool
# From source
# Or directly (once published)
As a Library
Add to your Cargo.toml:
[]
= { = "https://github.com/aayushadhikari7/aegis" }
CLI Usage
Running WebAssembly
# Run a function with arguments
# Output: Result: 15
# Run the default function (_start or main)
# Run with resource limits
# Show execution metrics
Granting Permissions
By default, WASM code has zero permissions. You grant what it needs:
# Allow reading from /data directory
# Allow reading and writing to /tmp
# Allow logging output
# Allow access to system clock
# Combine permissions
Validating Modules
Check if a WASM file is valid before running:
# Output: Module is valid
# Output: Module is invalid: ...
Inspecting Modules
See what a WASM module contains:
# Show everything
# Show only exports (functions you can call)
# Show only imports (what the module needs)
Example output:
Module: plugin.wasm
Exports (3):
add [function]: (i32, i32) -> (i32)
multiply [function]: (i32, i32) -> (i32)
memory [memory]: 1 pages
Imports (1):
env.log [function]: (i32) -> ()
Output Formats
# Human-readable (default)
# JSON output
# Compact JSON (single line)
All CLI Options
aegis run <MODULE> [OPTIONS] [-- ARGS...]
Options:
-e, --function <NAME> Function to call (default: _start or main)
--memory-limit <BYTES> Max memory in bytes (default: 64MB)
--fuel-limit <UNITS> Max CPU fuel units (default: 1B)
--timeout <SECONDS> Max execution time (default: 30s)
--allow-read <PATH> Grant read access to path
--allow-write <PATH> Grant read/write access to path
--allow-logging Enable logging output
--allow-clock Enable clock/time access
--metrics Show execution metrics
-f, --format <FORMAT> Output format: human, json, json-compact
-v, --verbose Increase verbosity (-v, -vv, -vvv)
-q, --quiet Suppress non-essential output
Library Usage
Basic Example
use *;
use Duration;
Loading WASM from Different Sources
// From a file
let module = runtime.load_file?;
// From bytes (e.g., uploaded by user)
let wasm_bytes: = receive_upload;
let module = runtime.load_bytes?;
// From WAT text format (useful for testing)
let module = runtime.load_wat?;
Granting Capabilities
use *;
let runtime = builder
.with_memory_limit
.with_fuel_limit
// Allow reading from specific paths
.with_filesystem
// Allow reading AND writing to specific paths
.with_filesystem
// Allow logging
.with_logging
// Allow clock access
.with_clock
.build?;
Registering Host Functions
Let WASM code call your Rust functions:
let mut sandbox = runtime.sandbox.build?;
// Register a function that WASM can call
sandbox.register_func?;
sandbox.register_func?;
sandbox.load_module?;
sandbox.call_void?;
Getting Execution Metrics
let mut sandbox = runtime.sandbox.build?;
sandbox.load_module?;
let result: i32 = sandbox.call?;
// Check how much resources were used
let metrics = sandbox.metrics;
println!;
println!;
println!;
Handling Errors
use *;
match sandbox.
Reusing Sandboxes
let mut sandbox = runtime.sandbox.build?;
sandbox.load_module?;
// Process multiple inputs with the same sandbox
for input in inputs
// Or reset and reuse
sandbox.reset;
sandbox.load_module?;
Features
Resource Limits
| Resource | What it Limits | Default |
|---|---|---|
| Memory | Max RAM the code can use | 64 MB |
| Fuel | Max CPU instructions (deterministic) | 1 billion |
| Timeout | Max wall-clock time | 30 seconds |
| Stack | Max call stack depth | 512 KB |
Capabilities (Permissions)
| Capability | What it Allows |
|---|---|
| Filesystem | Read/write specific directories |
| Network | Connect to specific hosts |
| Logging | Print output |
| Clock | Access system time |
Principle: Code has zero permissions by default. You explicitly grant what it needs.
Supported Value Types
The CLI and library support these WASM types:
| Type | Example |
|---|---|
i32 |
42, -17 |
i64 |
9999999999 |
f32 |
3.14 |
f64 |
3.141592653589793 |
Security Model
┌─────────────────────────────────────┐
│ Untrusted WASM Code │
├─────────────────────────────────────┤
│ Capability Layer (Permissions) │ ← Can it access this resource?
├─────────────────────────────────────┤
│ Resource Limiter (Memory/CPU) │ ← Has it exceeded limits?
├─────────────────────────────────────┤
│ Wasmtime Sandbox (Memory Safety) │ ← Is the code valid?
└─────────────────────────────────────┘
Guarantees:
- Code cannot access anything you don't explicitly allow
- Code cannot use more resources than you allocate
- Code cannot crash your application
- Code cannot escape the sandbox
Project Structure
| Crate | Description |
|---|---|
aegis |
Main library - start here |
aegis-core |
Low-level engine and sandbox |
aegis-capability |
Permission system |
aegis-resource |
Memory/CPU/time limits |
aegis-host |
Host function registration |
aegis-observe |
Metrics and monitoring |
aegis-cli |
Command-line tool |
Requirements
- Rust 1.85+
- Works on Linux, macOS, and Windows
License
Dual-licensed under:
Choose whichever you prefer.
Contributing
Contributions welcome! Feel free to:
- Open issues for bugs or feature requests
- Submit pull requests
- Improve documentation