Security Measures for TinyBus Admitted Native Modules in OpenHuman
OpenHuman implements a defense-in-depth security model for TinyBus admitted native modules that includes cryptographic SHA-256 verification, strict ABI compatibility gates, runtime sandboxing with panic isolation, and comprehensive audit logging to prevent unauthorized or compromised code from executing in the core process.
The OpenHuman runtime extends its capabilities through the TinyBus module system, which allows TinyBus admitted native modules to be dynamically loaded into the core process. When admitting these native extensions, the framework enforces a multi-layered security protocol designed to guarantee that only trusted, compatible code gains execution privileges according to the source code in tinyhumansai/openhuman.
Manifest Validation and Cryptographic Integrity
Every TinyBus module must ship a manifest that declares supported ABI versions, required TinyBus versions, and allowed capabilities. The core parses this manifest in src/openhuman/modules/registry.rs and rejects any module that does not declare the exact ABI version the core expects.
Before loading, the system performs SHA-256 digest verification. The manifest contains a cryptographic hash of the module binary, and at load time the core computes the hash of the downloaded file and compares it with the manifest entry. A mismatch aborts the load immediately, preventing tampered binaries from execution. This logic resides in src/openhuman/modules/registry.rs between lines 45-62.
ABI Compatibility Gates
OpenHuman enforces a two-sided ABI gate to prevent version conflicts. The core checks that the module's compiled TinyBus ABI matches the host's ABI down to the major and minor version numbers. This check, implemented in src/openhuman/modules/mod.rs at lines 30-38, stops modules built against incompatible TinyBus versions from being linked into the core process.
Runtime Sandboxing and Fault Isolation
Native modules are loaded via dlopen into the same address space, but the TinyBus runtime isolates them behind bounded queues, timeouts, and panic-catchers. Any panic occurring within a module is caught and converted into a module-failure event rather than crashing the entire process. This sandboxing implementation appears in src/openhuman/modules/loader.rs at lines 78-95.
Compile-Time Configuration and Fail-Closed Defaults
The framework supports configuration gating through the core's DomainSet and Cargo feature flags. When the modules feature is disabled at compile time, the stubs become compile-time-only and the admission code is not linked, guaranteeing that no module-related code can be invoked. This gating logic is defined in src/core/runtime/builder.rs at lines 112-123.
If a module fails any validation check, the core implements fail-closed defaults by registering the module as "unavailable" and continuing operation with built-in fallback implementations. This ensures that broken or untrusted modules never silently degrade functionality. The failure handling is implemented in src/openhuman/modules/loader.rs at lines 110-118.
Auditability and Event Logging
Every admitted module generates a ModuleLoadEvent on the global event bus. These logs include the module name, hash, checksum result, and load outcome, making post-mortem analysis straightforward. The event definitions and bus integration reside in src/core/event_bus/modules.rs.
Practical Implementation Examples
Loading a Module with Full Verification
use openhuman::modules::{ModuleRegistry, ModuleLoader};
use std::path::Path;
fn load_trusted_module(name: &str, dir: &Path) -> Result<(), ModuleLoadError> {
// 1. Resolve the module entry from the compiled-in registry
let entry = ModuleRegistry::lookup(name)?;
// 2. Download the artifact and verify its SHA-256 digest
let artifact = entry.fetch_artifact(dir)?;
entry.verify_digest(&artifact)?;
// 3. Perform ABI compatibility check
entry.ensure_abi_compatible()?;
// 4. Load the module with TinyBus runtime; panics are caught
ModuleLoader::load(&artifact)
}
Handling Load Failures Gracefully
match load_trusted_module("tinydocs", &modules_dir) {
Ok(_) => log::info!("tinydocs module loaded successfully"),
Err(e) => {
log::error!("Failed to load tinydocs: {}", e);
// The core falls back to its built-in stub implementation
fallback_to_builtin("tinydocs");
}
}
Subscribing to Module Load Events
use openhuman::core::event_bus::EventBus;
fn subscribe_to_module_loads(bus: &EventBus) {
bus.subscribe_global("modules.load", |event| {
println!("Module load event: {:?}", event);
});
}
Summary
- Manifest validation and SHA-256 verification in
registry.rsensure only cryptographically intact modules are considered for loading. - Two-sided ABI gates in
mod.rsprevent version mismatches between the core and native modules. - Runtime sandboxing with panic-catching and bounded queues in
loader.rsisolates faults to prevent core process crashes. - Compile-time feature gates in
builder.rsallow complete elimination of module loading code when not required. - Fail-closed defaults ensure that validation failures result in safe fallback to built-in implementations rather than degraded operation.
- Comprehensive audit logging via
ModuleLoadEventprovides full traceability of module admission decisions.
Frequently Asked Questions
What happens if a TinyBus module fails the SHA-256 checksum verification?
If the computed hash of the module binary does not match the SHA-256 digest declared in the manifest, the core aborts the loading process immediately. The module is marked as unavailable, and the system falls back to built-in implementations without executing the compromised binary.
How does OpenHuman prevent ABI version mismatches in native modules?
The core enforces a two-sided ABI compatibility check that verifies the module's compiled TinyBus ABI matches the host's ABI version exactly. This check occurs in src/openhuman/modules/mod.rs before any dynamic linking occurs, preventing incompatible modules from being loaded.
Can the native module system be completely disabled at compile time?
Yes. Through Cargo feature gates and the DomainSet configuration shown in src/core/runtime/builder.rs, the entire modules family can be disabled at compile time. When disabled, only compile-time stubs remain, and no module admission code is linked into the final binary.
What logging is available when a module fails to load?
Every module load attempt generates a ModuleLoadEvent on the global event bus, implemented in src/core/event_bus/modules.rs. These events include the module name, expected hash, verification results, and final load status, providing complete audit trails for security analysis.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →