WASM Secure Sandbox - Quick Reference Guide
WASM Secure Sandbox - Quick Reference Guide
Status: Production Architecture Date: 2025-11-10 For: Implementation Teams
Security Model at a Glance
Five-Layer Defense-in-Depth
Layer 5: Observability ← Audit logging, metrics, alertsLayer 4: Policy ← Capability checks, quotasLayer 3: Memory Safety ← Pointer validation, bounds checkingLayer 2: Runtime Isolation ← WASI, file/network isolationLayer 1: Wasmtime ← Hardware-backed memory sandboxingSecurity Properties:
- Memory Safety: 100% pointer validation
- Isolation: Modules cannot access each other
- Resource Bounds: CPU/memory limits enforced
- No Unsafe FFI: All host functions validated
- Audit Trail: Complete execution history
Resource Limits Quick Reference
Pre-Configured Profiles
| Profile | Memory | CPU Time | Use Case |
|---|---|---|---|
| Untrusted | 4MB | 500ms | Unknown code, maximum security |
| Database Only | 16MB | 2s | Standard stored procedures |
| Standard | 64MB | 5s | Trusted procedures (default) |
| Trusted | 256MB | 30s | Privileged operations |
Applying Limits
// Example 1: Conservative limitslet limits = WasmResourceLimits::conservative();let runtime = WasmRuntime::new_with_limits(limits);
// Example 2: Custom limitslet limits = WasmResourceLimits { max_memory_bytes: 32 * 1024 * 1024, // 32MB max_execution_time_ms: 3000, // 3 seconds max_allocation_size: 2 * 1024 * 1024, // 2MB ..Default::default()};Capability Model
Security Profiles
// Minimal - No capabilities (safest)SecurityProfile::minimal()
// Database Only - Read/query onlySecurityProfile::database_only() ├─ DatabaseRead ✓ ├─ DatabaseQuery ✓ ├─ LogAccess ✓ └─ FilesystemRead ✗ └─ NetworkClient ✗
// Standard - Common operationsSecurityProfile::standard() ├─ DatabaseRead ✓ ├─ DatabaseWrite ✓ ├─ DatabaseTransaction ✓ ├─ ClockAccess ✓ ├─ RandomAccess ✓ └─ NetworkClient ✗
// Elevated - Privileged accessSecurityProfile::elevated() ├─ All database capabilities ✓ ├─ FilesystemRead ✓ (restricted paths) ├─ NetworkClient ✓ (allowlist only) └─ NetworkServer ✗Custom Capability Sets
let mut profile = SecurityProfile::minimal();
// Grant specific capabilitiesprofile.capabilities.insert(Capability::DatabaseRead);profile.capabilities.insert(Capability::ClockAccess);
// Restrict file systemprofile.allowed_paths.push(PathBuf::from("/tmp/wasm-data"));profile.denied_paths.push(PathBuf::from("/etc"));Safe Memory API
Core Operations
// Read bytes (max 1MB per call)let data: Vec<u8> = memory_bridge.read_bytes(ptr, len)?;
// Write bytesmemory_bridge.write_bytes(ptr, &data)?;
// Read string (UTF-8 validated)let text: String = memory_bridge.read_string(ptr, len)?;
// Read typed value (alignment checked)let value: u64 = memory_bridge.read_typed(ptr)?;
// Allocate (tracked for double-free prevention)let ptr: u32 = memory_bridge.allocate(size)?;
// Deallocate (validates prior allocation)memory_bridge.deallocate(ptr, size)?;Validation Guarantees
Every memory operation includes:
- Null pointer check
- Length validation (< 1MB)
- Bounds checking (linear memory)
- Alignment validation (typed reads)
- Escape pattern detection
- Allocation tracking
Integration Examples
Query Executor
// Execute stored procedure from SQLlet result = wasm_executor.execute_stored_procedure( "calculate_discount", // module name "apply_rules", // function name vec![customer_data], // arguments SecurityProfile::database_only(),).await?;Event Triggers
-- Register WASM triggerCREATE TRIGGER validate_order_wasmBEFORE INSERT ON ordersFOR EACH ROWEXECUTE PROCEDURE wasm_call('validate_order', NEW);// Register programmaticallywasm_triggers.register_trigger( "validate_order_wasm", "order_validator", // module "validate", // function EventType::BeforeInsert,).await?;CDC Pipeline
// Register CDC transformercdc_integration.register_transformer( "enrich_customer", "enrichment_module", "transform_event",).await?;Monitoring & Alerting
Key Metrics
wasm_executions_total{status="success|failure"}wasm_execution_time_seconds{quantile="0.5|0.95|0.99"}wasm_memory_usage_bytes{stat="average|peak"}wasm_security_events_total{type="validation_failure|escape_attempt"}wasm_cache_operations_total{result="hit|miss|eviction"}Alert Thresholds (Recommended)
AlertThresholds { max_escape_attempts: 10, // Alert after 10 attempts max_validation_failures: 100, // Alert after 100 failures max_execution_time_ms: 5000, // Alert if >5s execution max_memory_usage_percent: 90.0, // Alert at 90% memory max_error_rate_percent: 5.0, // Alert at 5% error rate}Audit Events
All executions are logged with:
- Module hash and function name
- Execution time and resource usage
- Security violations (if any)
- Input/output data (configurable)
- Timestamp and user context
Performance Characteristics
Overhead Analysis
| Operation | Overhead | Impact |
|---|---|---|
| Pointer validation | 50ns | Negligible |
| Allocation tracking | 10ns | Negligible |
| Capability check | 5ns | Negligible |
| Fuel metering | 1-2% CPU | Low |
| Total | <1ms + 2% CPU | Acceptable |
Optimization Tips
-
Use module caching
runtime.enable_cache(true); // Reuse compiled modules -
Pool instances
runtime.enable_pooling(true); // Reuse instances -
Choose appropriate compilation tier
CompilationTier::Optimizing // Slower compile, faster executionCompilationTier::Baseline // BalancedCompilationTier::Interpreter // Fast compile, slower execution -
Batch operations
// Process multiple items in single callwasm_call("batch_process", items)
Security Best Practices
Module Development
-
Minimize capabilities
- Request only required capabilities
- Use most restrictive profile possible
-
Validate inputs
- Check all host function inputs
- Validate data before processing
-
Handle errors gracefully
- Don’t panic on invalid input
- Return proper error codes
-
Resource awareness
- Be mindful of memory allocations
- Avoid infinite loops
- Clean up resources
Deployment
-
Sign modules
module_signer.sign(module_bytes, private_key)?; -
Verify signatures
module_verifier.verify(module_bytes, expected_hash)?; -
Monitor metrics
- Set up Prometheus/Grafana
- Configure alerts
- Review audit logs regularly
-
Update regularly
- Keep Wasmtime up to date
- Review security advisories
- Patch vulnerabilities promptly
Troubleshooting
Common Errors
Error: WasmError::OutOfBounds
- Cause: Pointer outside linear memory
- Fix: Validate pointer comes from WASM allocator
- Prevention: Use safe memory API
Error: WasmError::Timeout(5000)
- Cause: Execution exceeded time limit
- Fix: Optimize algorithm or increase limit
- Prevention: Profile code, avoid infinite loops
Error: WasmError::MemoryQuotaExceeded
- Cause: Requested memory exceeds quota
- Fix: Reduce memory usage or increase quota
- Prevention: Reuse allocations, free promptly
Error: WasmError::DoubleFree
- Cause: Attempted to free same pointer twice
- Fix: Check allocation tracking logic
- Prevention: Use safe memory API exclusively
Error: WasmError::CapabilityDenied
- Cause: Missing required capability
- Fix: Add capability to security profile
- Prevention: Test with actual profile
Debug Mode
// Enable verbose logginglet runtime = WasmRuntime::new() .with_debug_mode(true) .with_trace_execution(true);
// Check metricslet metrics = runtime.metrics();println!("Escape attempts: {}", metrics.escape_attempts);
// Review audit loglet events = audit_log.get_recent(100);for event in events { println!("{:?}", event);}Testing Checklist
Security Tests
- Memory bounds enforcement
- CPU time limit enforcement
- Capability enforcement
- Pointer validation
- Double-free prevention
- Allocation tracking
- Escape attempt detection
- Null pointer rejection
- Integer overflow prevention
Integration Tests
- Query executor integration
- Event trigger integration
- CDC pipeline integration
- Module caching
- Instance pooling
- Error handling
- Metric collection
- Audit logging
Performance Tests
- Execution overhead < 5%
- Validation overhead < 100μs
- Memory overhead acceptable
- Cache hit rate > 80%
- Pool utilization > 70%
Migration Guide
Replacing Unsafe Code
Before:
// UNSAFE - No validationunsafe { let data = std::slice::from_raw_parts(ptr, len); process(data);}After:
// SAFE - Full validationlet data = memory_bridge.read_bytes(ptr, len)?;process(&data);Updating Host Functions
Before:
pub fn host_function(ptr: *const u8, len: usize) -> i32 { unsafe { let data = std::slice::from_raw_parts(ptr, len); // process... }}After:
pub fn host_function( ctx: &WasmContext, ptr: u32, len: u32,) -> Result<i32> { let data = ctx.memory_bridge().read_bytes(ptr, len)?; // process... Ok(result)}Quick Commands
Create Runtime
// Default configurationlet runtime = WasmRuntime::new()?;
// Custom configurationlet runtime = WasmRuntime::with_config(WasmRuntimeConfig { resource_limits: WasmResourceLimits::conservative(), enable_cache: true, enable_pooling: true, ..Default::default()})?;Load Module
let module = runtime.compile_module( "my_module".to_string(), wasm_bytes,).await?;Execute Function
let result = runtime.execute( "my_module", "my_function", vec![Value::I32(42)],).await?;Check Metrics
let stats = runtime.stats();println!("Cached modules: {}", stats.cached_modules);println!("Active instances: {}", stats.active_instances);Support & Resources
Documentation
- Main Architecture:
/docs/architecture/WASM_SECURE_SANDBOX_DESIGN.md - Security Audit:
/docs/WASM_SECURITY_AUDIT.md - User Guide:
/docs/user-guides/WASM_PROCEDURES.md
Code Locations
- Runtime:
/heliosdb-wasm/src/runtime.rs - Sandbox:
/heliosdb-wasm/src/sandbox.rs - Security:
/heliosdb-wasm/src/pointer_validation.rs - Limits:
/heliosdb-wasm/src/resource_limits.rs
External Resources
- Wasmtime Docs: https://docs.wasmtime.dev/
- WASI Spec: https://wasi.dev/
- WebAssembly Docs: https://webassembly.org/
Last Updated: 2025-11-10 Version: 1.0