You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
wazero is a zero-dependency, pure-Go WebAssembly runtime. It executes WASM modules in a secure sandbox without CGO or external C libraries. In this project it powers the WasmGuard system — the runtime enforcement layer for DIFC (Decentralized Information Flow Control) security policies.
api.Memory.Read/Write/Grow/ReadUint32Le — linear memory bridge
sys.ExitError — distinguishing WASI process exits from traps
Research Findings
The project uses wazero at a sophisticated level: dual memory management strategies (guard allocator vs. raw memory fallback), adaptive output buffers with guard-signalled size hints (return code -2), trap poisoning for corrupted module detection, and context-based cleanup. Overall this is excellent usage of wazero's capabilities.
Recent Updates
v1.11.0: JIT compiler performance improvements; WASI preview2 work in progress
Disk-backed compilation cache API has been stable since v1.0
context.WithoutCancel pattern for dealloc cleanup (already used correctly here)
Best Practices Already Applied ✅
WithCloseOnContextDone(true) for server use
Host modules named "env" per WASM convention
Compilation cache shared process-wide
WithStartFunctions() to suppress auto-start
Stdin isolated with WithStdin(strings.NewReader(""))
Improvement Opportunities
🏃 Quick Wins
1. Race condition in ConfigureGlobalCompilationCache (wasm.go ~lines 42–71)
The current code reads oldCache under the lock, releases it, then re-acquires to conditionally set the new value. Two concurrent callers could race on the replacement:
// Current (racy):globalCompilationCacheMu.Lock()
oldCache:=globalCompilationCacheglobalCompilationCacheMu.Unlock() // lock released here// another goroutine could set globalCompilationCache here...ifoldCache==nil {
globalCompilationCacheMu.Lock()
globalCompilationCache=cache// ...causing a lost updateglobalCompilationCacheMu.Unlock()
}
// Suggested fix: set atomically before releasingglobalCompilationCacheMu.Lock()
oldCache:=globalCompilationCacheglobalCompilationCache=cacheglobalCompilationCacheMu.Unlock()
// Close oldCache outside the lockifoldCache!=nil {
iferr:=oldCache.Close(ctx); err!=nil { ... }
}
Note: the function is documented as "called during process startup" which reduces practical risk, but the locking should still be correct.
2. isWasmTrap string matching (wasm_parse.go line 87)
strings.Contains(err.Error(), "wasm error:") relies on wazero's internal error string format, which is not a stable API contract. Add a version annotation:
// Matches wazero's internal error prefix as of v1.x; re-verify on wazero upgrades.returnstrings.Contains(err.Error(), "wasm error:")
3. interface{} → any (wasm.go multiple locations)
The WASM bridge uses interface{} in several function signatures. The project targets Go 1.25 where any is the idiomatic alias. Simple find-and-replace within the guard package.
✨ Feature Opportunities
1. WASI Preview2 / Component Model
wazero is building preview2 support. Future guard SDKs could use the component model for a structured, type-safe ABI instead of the current manual JSON-over-linear-memory bridge. Worth tracking.
2. Interpreter mode in tests
Test WASM modules in wasm_test.go use the default compiler config. wazero.NewRuntimeConfigInterpreter() in tests would avoid JIT overhead and improve portability across CPU architectures.
3. Typed memory helpers
wazero's api.Memory has ReadUint32Le (already used at line 223). Audit for any remaining manual 4-byte raw reads that could use this typed helper.
Minor: simplify with a one-liner or helper for readability.
Test WAT source comments minimalGuardWasm in wasm_test.go is raw hex with no WAT source comment. blockingGuardWasm correctly documents its WAT source inline. Add the same for minimalGuardWasm.
🔧 General Improvements
Shutdown sequencing documentation: CloseGlobalCompilationCache requires all WasmGuard runtimes to be closed first. Consider adding a cross-reference to where in the graceful shutdown path Registry.Close() is called, so the ordering constraint is visible from both sides.
Recommendations (Prioritized)
High: Fix the race in ConfigureGlobalCompilationCache — hold the lock across read-and-set
Medium: Add wazero version annotation to isWasmTrap's string-matching fallback
Low: Modernize interface{} → any in guard package
Low: Add WAT source comment to minimalGuardWasm in tests
Watch: Track wazero WASI preview2 progress for future guard ABI improvements
Next Steps
Review and fix ConfigureGlobalCompilationCache race condition
Add wazero version annotation to isWasmTrap string check
Modernize interface{} → any in guard package
Document shutdown sequencing between Registry.Close() and CloseGlobalCompilationCache
🐹 Go Fan Report: tetratelabs/wazero
Module Overview
wazero is a zero-dependency, pure-Go WebAssembly runtime. It executes WASM modules in a secure sandbox without CGO or external C libraries. In this project it powers the
WasmGuardsystem — the runtime enforcement layer for DIFC (Decentralized Information Flow Control) security policies.Current version:
v1.11.0Current Usage in gh-aw-mcpg
wasm.go,wasm_parse.go,wasm_test.go,cmd/proxy.go)wazero,wazero/api,wazero/imports/wasi_snapshot_preview1,wazero/sys)NewRuntimeConfigCompiler()+WithCloseOnContextDone(true)— JIT with context cleanupNewCompilationCache()/NewCompilationCacheWithDir()— in-memory and disk-backed JIT cachingNewHostModuleBuilder("env")— host function injection (call_backend,host_log)wasi_snapshot_preview1.Instantiate— WASI support for TinyGo-compiled guardsNewModuleConfig().WithStartFunctions().WithStdin(...)— module isolationapi.Memory.Read/Write/Grow/ReadUint32Le— linear memory bridgesys.ExitError— distinguishing WASI process exits from trapsResearch Findings
The project uses wazero at a sophisticated level: dual memory management strategies (guard allocator vs. raw memory fallback), adaptive output buffers with guard-signalled size hints (return code
-2), trap poisoning for corrupted module detection, and context-based cleanup. Overall this is excellent usage of wazero's capabilities.Recent Updates
context.WithoutCancelpattern for dealloc cleanup (already used correctly here)Best Practices Already Applied ✅
WithCloseOnContextDone(true)for server use"env"per WASM conventionWithStartFunctions()to suppress auto-startWithStdin(strings.NewReader(""))Improvement Opportunities
🏃 Quick Wins
1. Race condition in
ConfigureGlobalCompilationCache(wasm.go~lines 42–71)The current code reads
oldCacheunder the lock, releases it, then re-acquires to conditionally set the new value. Two concurrent callers could race on the replacement:Note: the function is documented as "called during process startup" which reduces practical risk, but the locking should still be correct.
2.
isWasmTrapstring matching (wasm_parse.goline 87)strings.Contains(err.Error(), "wasm error:")relies on wazero's internal error string format, which is not a stable API contract. Add a version annotation:3.
interface{}→any(wasm.gomultiple locations)The WASM bridge uses
interface{}in several function signatures. The project targets Go 1.25 whereanyis the idiomatic alias. Simple find-and-replace within the guard package.✨ Feature Opportunities
1. WASI Preview2 / Component Model
wazero is building preview2 support. Future guard SDKs could use the component model for a structured, type-safe ABI instead of the current manual JSON-over-linear-memory bridge. Worth tracking.
2. Interpreter mode in tests
Test WASM modules in
wasm_test.gouse the default compiler config.wazero.NewRuntimeConfigInterpreter()in tests would avoid JIT overhead and improve portability across CPU architectures.3. Typed memory helpers
wazero's
api.MemoryhasReadUint32Le(already used at line 223). Audit for any remaining manual 4-byte raw reads that could use this typed helper.📐 Best Practice Alignment
WithNameinline closure (wasm.goline 193–198)Minor: simplify with a one-liner or helper for readability.
Test WAT source comments
minimalGuardWasminwasm_test.gois raw hex with no WAT source comment.blockingGuardWasmcorrectly documents its WAT source inline. Add the same forminimalGuardWasm.🔧 General Improvements
Shutdown sequencing documentation:
CloseGlobalCompilationCacherequires allWasmGuardruntimes to be closed first. Consider adding a cross-reference to where in the graceful shutdown pathRegistry.Close()is called, so the ordering constraint is visible from both sides.Recommendations (Prioritized)
ConfigureGlobalCompilationCache— hold the lock across read-and-setisWasmTrap's string-matching fallbackinterface{}→anyin guard packageminimalGuardWasmin testsNext Steps
ConfigureGlobalCompilationCacherace conditionisWasmTrapstring checkinterface{}→anyin guard packageRegistry.Close()andCloseGlobalCompilationCacheGenerated by Go Fan 🐹
References:
Note
🔒 Integrity filter blocked 9 items
The following items were blocked because they don't meet the GitHub integrity level.
get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_latest_release: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_latest_release: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_latest_release: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".To allow these resources, lower
min-integrityin your GitHub frontmatter: