Skip to content

WASM Procedures: Security Model (Planned Design)

Part of: WASM Procedures User Guide


WASM procedures are designed around a capability-based security model with fine-grained access control.

Capability-Based Security

In this design, every procedure explicitly requests capabilities. By default, procedures have zero permissions.

13 Capability Types

CapabilityDescriptionRisk Level
DatabaseReadRead from database tablesLow
DatabaseWriteWrite to database tablesMedium
DatabaseQueryExecute arbitrary SQL queriesMedium
DatabaseTransactionBegin/commit/rollback transactionsMedium
FilesystemReadRead files from allowed pathsMedium
FilesystemWriteWrite files to allowed pathsHigh
NetworkClientMake outbound network connectionsHigh
NetworkServerListen for network connectionsCritical
RandomAccessAccess random number generationLow
ClockAccessAccess system clock/timeLow
EnvironmentReadRead environment variablesMedium
LogAccessWrite to procedure logsLow
CryptoAccessCryptographic operationsLow

Security Profiles

The design defines these predefined security profiles:

Minimal Profile

Most restrictive, zero capabilities.

-- Planned syntax for the upcoming WASM procedures feature; the current server does not accept it.
CREATE PROCEDURE safe_calculation(x INT, y INT)
RETURNS INT
LANGUAGE wasm
SECURITY PROFILE 'minimal'
AS '/path/to/procedure.wasm';

Capabilities: None Max Memory: 1 MB Max CPU Time: 100 ms Use Case: Pure computational procedures

Database-Only Profile

Read-only database access.

-- Planned syntax for the upcoming WASM procedures feature; the current server does not accept it.
SECURITY PROFILE 'database_only'

Capabilities:

  • DatabaseRead
  • DatabaseQuery
  • LogAccess

Max Memory: 16 MB Max CPU Time: 1 second Use Case: Reporting, analytics

Standard Profile

Typical database operations.

-- Planned syntax for the upcoming WASM procedures feature; the current server does not accept it.
SECURITY PROFILE 'standard' -- Default

Capabilities:

  • DatabaseRead
  • DatabaseWrite
  • DatabaseQuery
  • DatabaseTransaction
  • RandomAccess
  • ClockAccess
  • LogAccess
  • CryptoAccess

Max Memory: 64 MB Max CPU Time: 10 seconds Use Case: Business logic, data processing

Elevated Profile

Includes filesystem and network access.

-- Planned syntax for the upcoming WASM procedures feature; the current server does not accept it.
SECURITY PROFILE 'elevated'

Capabilities:

  • All Standard capabilities
  • FilesystemRead
  • NetworkClient
  • EnvironmentRead

Max Memory: 256 MB Max CPU Time: 60 seconds Use Case: ETL, API integrations

Custom Security Profiles

Create custom profiles for specific needs:

-- Planned syntax for the upcoming WASM procedures feature; the current server does not accept it.
CREATE SECURITY PROFILE 'api_integration' AS (
capabilities: ['DatabaseRead', 'NetworkClient', 'LogAccess', 'CryptoAccess'],
max_memory_bytes: 32000000, -- 32 MB
max_cpu_time_ms: 5000, -- 5 seconds
max_network_connections: 5,
allowed_paths: [],
denied_paths: [],
allow_nondeterministic: true
);
-- Use custom profile
CREATE PROCEDURE fetch_external_data()
LANGUAGE wasm
SECURITY PROFILE 'api_integration'
AS '/path/to/procedure.wasm';

Capabilities Are Fixed per Procedure

A procedure gets its capabilities from the security profile named in CREATE PROCEDURE. It cannot request more while it runs: the WASM host has no function for requesting a capability, and no HTTP or socket functions. The host functions a module can import are listed in Host Functions; the published Go SDK wraps them.

To let a procedure use data from an external service, load that data into a table outside the procedure and have the procedure read the table.

System Call Filtering

HeliosDB automatically filters dangerous system calls:

Blocked by default:

  • proc_exit (process termination)
  • proc_raise (signal raising)
  • Socket operations (unless NetworkClient capability granted)
  • File operations (unless FilesystemRead/FilesystemWrite granted)

Custom filters:

-- Planned syntax for the upcoming WASM procedures feature; the current server does not accept it.
CREATE SECURITY PROFILE 'restricted' AS (
capabilities: ['DatabaseRead'],
syscall_filter: 'deny_list',
allowed_syscalls: ['fd_read', 'fd_write', 'clock_time_get'],
denied_syscalls: ['sock_connect', 'sock_bind']
);

Resource Limits

Every procedure execution is subject to resource limits:

Memory Limits

// Procedure can allocate up to profile.max_memory_bytes
let large_vec = vec![0u8; 10_000_000]; // 10 MB
// Exceeding limit causes:
// Error: Resource limit exceeded: Memory quota exceeded: 67108864 bytes

CPU Time Limits

// Long-running operation
for i in 0..1_000_000_000 {
// Heavy computation
}
// After max_cpu_time_ms:
// Error: Timeout: execution exceeded 10000ms

Fuel Metering

WASM fuel tracks instruction count:

// Each WASM instruction consumes fuel
let mut sum = 0;
for i in 0..100_000 {
sum += i; // Consumes ~3 fuel units
}
// When fuel exhausted:
// Error: Resource limit exceeded: Fuel exhausted

Deterministic Execution

For reproducible results, enable determinism checking:

-- Planned syntax for the upcoming WASM procedures feature; the current server does not accept it.
CREATE SECURITY PROFILE 'deterministic' AS (
capabilities: ['DatabaseRead'],
allow_nondeterministic: false -- Blocks random, time, network
);

Blocked operations in deterministic mode:

  • Random number generation - Non-deterministic
  • Wall-clock time - Non-deterministic
  • Floating-point NaN comparisons

Security Best Practices

1. Principle of Least Privilege

Request only needed capabilities.

-- Planned syntax for the upcoming WASM procedures feature; the current server does not accept it.
-- Good: Minimal capabilities
CREATE PROCEDURE calculate_tax(amount DECIMAL)
SECURITY PROFILE 'minimal';
-- Bad: Excessive capabilities
CREATE PROCEDURE calculate_tax(amount DECIMAL)
SECURITY PROFILE 'elevated';

2. Input Validation

Always validate inputs.

#[procedure]
fn process_order(order_id: i64) -> Result<(), String> {
if order_id <= 0 {
return Err("Invalid order ID".into());
}
// ...
}

3. SQL Injection Prevention

Use parameterized queries.

// Bad: SQL injection vulnerable
let sql = format!("SELECT * FROM users WHERE id = {}", user_id);
exec_sql(&sql)?;
// Good: Use parameterized queries (when available in SDK)
let stmt = prepare_statement("SELECT * FROM users WHERE id = ?")?;
let result = exec_prepared_with_params(stmt, &[user_id])?;

4. Error Handling

Never expose sensitive information.

// Bad: Leaks internal details
Err(format!("Database error: {}", internal_error))
// Good: Generic error message
Err("Operation failed".into())

5. Audit Logging

Log security-relevant operations.

log_info(&format!("User {} accessed resource {}", user_id, resource_id));

Navigation: