Skip to content

[go-fan] Go Module Review: tetratelabs/wazero #11491

Description

@github-actions

🐹 Go Fan Report: tetratelabs/wazero

Module Overview

wazero is a zero-dependency WebAssembly runtime for Go, written in pure Go with no CGo. It provides both a compiler (near-native speed) and interpreter engine, WASI support, and a rich embedding API for host functions — exactly the sandboxing primitive gh-aw-mcpg needs for its WASM guard system.

Current Usage in gh-aw-mcpg

  • Files: 6 files reference tetratelabs/wazero (internal/guard/wasm_lifecycle.go, wasm_exec.go, plus test files wasm_test.go, wasm_dispatch_test.go, wasm_parse_coverage_test.go, wasm_new_options_coverage_test.go)
  • Key APIs Used:
    • wazero.NewRuntimeConfigCompiler() with WithCloseOnContextDone(true) and WithMemoryLimitPages(512) (32 MiB hard cap) for production guards
    • wazero.NewRuntimeConfigInterpreter() in tests (faster startup, no JIT, good for short-lived test runtimes)
    • wazero.NewCompilationCache() / NewCompilationCacheWithDir() — a process-global shared compilation cache (globalCompilationCache) reused across all WasmGuard instances to avoid redundant JIT compilation
    • wasi_snapshot_preview1.Instantiate for WASI support
    • wazero.NewModuleConfig() with WithStartFunctions() (suppress _start), WithStdin(strings.NewReader("")) (stdin isolation from the MCP protocol stream), WithStdout/WithStderr redirection
    • Custom host functions bridging guest WASM calls to a BackendCaller interface

Research Findings

Latest release v1.12.0 (2026-08-17, same day as this review) is the most-recently-pushed direct dependency — great timing! The project already pins v1.12.0 in go.mod, so it's up to date.

Recent Updates

  • Continued hardening of interpreter/compiler engines and WASI parity fixes across recent releases.
  • Ongoing focus on memory-safety and resource-limiting APIs (WithMemoryLimitPages, WithCloseOnContextDone) — both of which this project already adopts, which is excellent alignment with upstream security guidance for sandboxing untrusted guest code.

Best Practices

  • Maintainers recommend wazero.NewRuntimeConfigCompiler() for production workloads needing near-native speed and NewRuntimeConfigInterpreter() for short-lived/test scenarios or platforms without JIT support — this project follows that split precisely (compiler for guards in production, interpreter in unit tests).
  • Sharing a single CompilationCache across runtimes to avoid recompiling identical WASM bytes is a documented pattern; the project's globalCompilationCache with a sync.Mutex-guarded swap (ConfigureGlobalCompilationCache) matches this recommendation closely.
  • WithCloseOnContextDone(true) is the documented way to guarantee a WASM guest can't hang indefinitely; already used for the main guard runtime.

Improvement Opportunities

🏃 Quick Wins

  • The rationale for WithMemoryLimitPages(512) and repeated NewRuntimeConfigInterpreter() calls in wasm_test.go (6+ occurrences) could be consolidated into a shared test helper (e.g. newTestRuntime(ctx)), reducing duplication and making future config changes a one-line edit.
  • Consider extracting the repeated moduleConfig := wazero.NewModuleConfig().WithName(...).WithStartFunctions().WithStdin(...).WithStdout(...).WithStderr(...) pattern into a shared builder function to keep stdin/stdout isolation guarantees consistent everywhere WASM modules are instantiated, including in tests.

✨ Feature Opportunities

  • wazero's compiler config exposes WithDebugInfoEnabled(bool) (default true). Since guard WASM binaries are untrusted third-party artifacts and this is a security-sensitive path, explicitly disabling debug info (WithDebugInfoEnabled(false)) for production guard runtimes could shave compile time/memory without functional loss, since this project doesn't symbolicate guest stack traces.
  • The in-memory compilation cache (wazero.NewCompilationCache()) has no explicit eviction bound. Given guards can be loaded from arbitrary WASM files (FindServerWASMGuardFile), consider defaulting long-running gateway deployments to the already-supported disk-backed cache (newCompilationCache(dir)) to bound memory growth.

📐 Best Practice Alignment

  • Current usage is already strongly idiomatic: WASI isolation, per-guest memory caps, context-cancellation-driven cleanup, and a shared compilation cache all match wazero's own recommended production patterns for sandboxing untrusted code. No corrections needed here.

🔧 General Improvements

  • Test files instantiate raw wazero.Runtime objects independently of the shared helpers in wasm_lifecycle.go (repeated across 6 test files). Centralizing this into a small helper in internal/guard would reduce risk of test/production config drift.

Module Summary

Field Value
Module github.com/tetratelabs/wazero
Version v1.12.0
Repository https://github.com/tetratelabs/wazero
Latest Release v1.12.0 (2026-08-17)
Last Reviewed 2026-08-19

Key Features

  • Pure Go, zero-CGo, zero-dependency WebAssembly runtime
  • Compiler (near-native) and Interpreter (portable) engines
  • WASI Preview 1 support (wasi_snapshot_preview1)
  • Memory limiting (WithMemoryLimitPages), context-based cancellation (WithCloseOnContextDone)
  • Shared/disk-backed compilation caching for fast repeated instantiation

References

Recommendations

  1. Consolidate test-only runtime construction into a shared helper to reduce duplication (low risk, low effort).
  2. Evaluate WithDebugInfoEnabled(false) for the production guard compiler config as a minor hardening/perf tweak.
  3. Consider defaulting to a disk-backed compilation cache in long-running gateway deployments to bound memory growth from arbitrarily many distinct guest WASM binaries.

Next Steps

  • Prototype the test-runtime helper and measure any reduction in test boilerplate.
  • Benchmark WithDebugInfoEnabled(false) compile-time/memory impact on a representative guard binary.
  • Discuss whether disk-backed compilation cache should become the default for containerized gateway deployments (already configurable via MCP_GATEWAY_WASM_CACHE_DIR).

Generated by Go Fan

Generated by Go Fan · auto · 45.4 AIC · ⊞ 11.9K ·

  • expires on Aug 26, 2026, 7:23 AM UTC

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions