WebAssembly Security Sandbox¶
Why WebAssembly for Security?¶
WebAssembly (Wasm) provides a sandboxed execution environment with:
- Memory Safety: Linear memory with bounds checking
- Capability-Based Security: Explicit imports for system access
- Deterministic Execution: Same inputs = same outputs
- Platform Independence: Runs anywhere with a Wasm runtime
Security Model¶
Memory Isolation¶
┌─────────────────────────────┐
│ Host Environment │
├─────────────────────────────┤
│ Wasm Runtime (Wasmtime) │
├─────────────────────────────┤
│ ┌───────────────────────┐ │
│ │ Linear Memory │ │
│ │ (Bounded, Isolated) │ │
│ └───────────────────────┘ │
│ Wasm Module │
└─────────────────────────────┘
Import/Export System¶
Wasm modules can only access what is explicitly provided:
// Host provides these functions
#[link(wasm_import_module = "host")]
extern "C" {
fn log_message(ptr: *const u8, len: usize);
fn get_timestamp() -> u64;
}
Implementing Secure Rules (Rust to Wasm)¶
Step 1: Write Detection Logic¶
#[no_mangle]
pub extern "C" fn check_file_access(path_ptr: *const u8, path_len: usize) -> i32 {
let path = unsafe {
std::str::from_utf8_unchecked(
std::slice::from_raw_parts(path_ptr, path_len)
)
};
// Check for sensitive paths
if path.contains("/etc/passwd") || path.contains("/etc/shadow") {
return 1; // Alert
}
0 // Normal
}
Step 2: Compile to Wasm¶
cargo build --target wasm32-wasi --release
Step 3: Load in Host (Go)¶
func loadRule(wasmPath string) (*wasmtime.Instance, error) {
engine := wasmtime.NewEngine()
store := wasmtime.NewStore(engine)
module, _ := wasmtime.NewModuleFromFile(engine, wasmPath)
return wasmtime.NewInstance(store, module, nil)
}
Best Practices¶
- Minimal Imports: Only expose necessary host functions
- Memory Limits: Set maximum memory pages
- Execution Timeouts: Prevent infinite loops
- Input Validation: Sanitize data before passing to Wasm
- Capability Tokens: Use WASI capabilities sparingly
Performance Considerations¶
| Aspect | Overhead |
|---|---|
| Call overhead | ~10ns per call |
| Memory access | Bounds check per access |
| Linear memory | Up to 4GB per instance |
| Instantiation | ~1ms for typical modules |
WasmSentinel Architecture¶
Events (eBPF) → Collector → Wasm Rules → Alert Handler
↑
Rule Hot-Reload