Skip to content

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, alerts
Layer 4: Policy ← Capability checks, quotas
Layer 3: Memory Safety ← Pointer validation, bounds checking
Layer 2: Runtime Isolation ← WASI, file/network isolation
Layer 1: Wasmtime ← Hardware-backed memory sandboxing

Security 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

ProfileMemoryCPU TimeUse Case
Untrusted4MB500msUnknown code, maximum security
Database Only16MB2sStandard stored procedures
Standard64MB5sTrusted procedures (default)
Trusted256MB30sPrivileged operations

Applying Limits

// Example 1: Conservative limits
let limits = WasmResourceLimits::conservative();
let runtime = WasmRuntime::new_with_limits(limits);
// Example 2: Custom limits
let 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 only
SecurityProfile::database_only()
├─ DatabaseRead ✓
├─ DatabaseQuery ✓
├─ LogAccess ✓
└─ FilesystemRead ✗
└─ NetworkClient ✗
// Standard - Common operations
SecurityProfile::standard()
├─ DatabaseRead ✓
├─ DatabaseWrite ✓
├─ DatabaseTransaction ✓
├─ ClockAccess ✓
├─ RandomAccess ✓
└─ NetworkClient ✗
// Elevated - Privileged access
SecurityProfile::elevated()
├─ All database capabilities
├─ FilesystemRead ✓ (restricted paths)
├─ NetworkClient ✓ (allowlist only)
└─ NetworkServer ✗

Custom Capability Sets

let mut profile = SecurityProfile::minimal();
// Grant specific capabilities
profile.capabilities.insert(Capability::DatabaseRead);
profile.capabilities.insert(Capability::ClockAccess);
// Restrict file system
profile.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 bytes
memory_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:

  1. Null pointer check
  2. Length validation (< 1MB)
  3. Bounds checking (linear memory)
  4. Alignment validation (typed reads)
  5. Escape pattern detection
  6. Allocation tracking

Integration Examples

Query Executor

// Execute stored procedure from SQL
let 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 trigger
CREATE TRIGGER validate_order_wasm
BEFORE INSERT ON orders
FOR EACH ROW
EXECUTE PROCEDURE wasm_call('validate_order', NEW);
// Register programmatically
wasm_triggers.register_trigger(
"validate_order_wasm",
"order_validator", // module
"validate", // function
EventType::BeforeInsert,
).await?;

CDC Pipeline

// Register CDC transformer
cdc_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"}
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

OperationOverheadImpact
Pointer validation50nsNegligible
Allocation tracking10nsNegligible
Capability check5nsNegligible
Fuel metering1-2% CPULow
Total<1ms + 2% CPUAcceptable

Optimization Tips

  1. Use module caching

    runtime.enable_cache(true); // Reuse compiled modules
  2. Pool instances

    runtime.enable_pooling(true); // Reuse instances
  3. Choose appropriate compilation tier

    CompilationTier::Optimizing // Slower compile, faster execution
    CompilationTier::Baseline // Balanced
    CompilationTier::Interpreter // Fast compile, slower execution
  4. Batch operations

    // Process multiple items in single call
    wasm_call("batch_process", items)

Security Best Practices

Module Development

  1. Minimize capabilities

    • Request only required capabilities
    • Use most restrictive profile possible
  2. Validate inputs

    • Check all host function inputs
    • Validate data before processing
  3. Handle errors gracefully

    • Don’t panic on invalid input
    • Return proper error codes
  4. Resource awareness

    • Be mindful of memory allocations
    • Avoid infinite loops
    • Clean up resources

Deployment

  1. Sign modules

    module_signer.sign(module_bytes, private_key)?;
  2. Verify signatures

    module_verifier.verify(module_bytes, expected_hash)?;
  3. Monitor metrics

    • Set up Prometheus/Grafana
    • Configure alerts
    • Review audit logs regularly
  4. 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 logging
let runtime = WasmRuntime::new()
.with_debug_mode(true)
.with_trace_execution(true);
// Check metrics
let metrics = runtime.metrics();
println!("Escape attempts: {}", metrics.escape_attempts);
// Review audit log
let 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 validation
unsafe {
let data = std::slice::from_raw_parts(ptr, len);
process(data);
}

After:

// SAFE - Full validation
let 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 configuration
let runtime = WasmRuntime::new()?;
// Custom configuration
let 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


Last Updated: 2025-11-10 Version: 1.0