Summary
Evaluator.Eval(ctx) for the Extism engine cannot be interrupted by context cancellation or timeout while the WASM guest runs. A guest that loops (or runs long) blocks the call indefinitely regardless of context.WithTimeout or cancel. The comment // Call the function (context handles timeout) at engines/extism/evaluator/evaluator.go:110 is incorrect.
Root cause
Neither of the two settings that would make wazero watch ctx.Done() is applied:
- The manifest is built with no
Timeout — engines/extism/compiler/internal/compile/compile.go:49-55.
- The default runtime config is
wazero.NewRuntimeConfig() with no .WithCloseOnContextDone(true) — engines/extism/compiler/options.go:111-113, engines/extism/compiler/internal/compile/settings.go:22.
In extism go-sdk v1.7.1, close-on-context-done is enabled only when manifest.Timeout > 0. With neither set, instance.CallWithContext(ctx, ...) (evaluator.go:112) runs to completion regardless of ctx.
The public constructor extism.FromExtismLoader (engines/extism/new.go) exposes no runtime-config option, so public-API callers have no workaround; only code reaching into compiler.WithRuntimeConfig(wazero.NewRuntimeConfig().WithCloseOnContextDone(true)) can opt in.
Reproduction (confirmed)
Eval with an already-cancelled context still ran the module to completion and returned map[greeting:Hello, World!] rather than a cancellation error.
Impact
High — there is no way to bound or abort WASM execution through the public API. A malicious or buggy guest hangs the caller's goroutine, and timeouts are silently ineffective.
Related defect
engines/extism/evaluator/evaluator.go:114-118: because cancellation never actually interrupts the call, reaching this branch means the guest failed for its own reason while ctx happened to be cancelled. The real error is then replaced with "execution cancelled: context canceled", discarding the cause. Wrap both errors (%w … %w), or prefer ctx.Err() only for wazero's exit-code-canceled sentinel.
Fix
Default the compile settings' RuntimeConfig to wazero.NewRuntimeConfig().WithCloseOnContextDone(true) (in compile.WithDefaultCompileSettings, compile.compile, and Compiler.applyDefaults), and/or set a manifest Timeout. Add a test asserting Eval with an expired context returns promptly with a cancellation error. Consider exposing a runtime-config or timeout option on FromExtismLoader.
Summary
Evaluator.Eval(ctx)for the Extism engine cannot be interrupted by context cancellation or timeout while the WASM guest runs. A guest that loops (or runs long) blocks the call indefinitely regardless ofcontext.WithTimeoutor cancel. The comment// Call the function (context handles timeout)atengines/extism/evaluator/evaluator.go:110is incorrect.Root cause
Neither of the two settings that would make wazero watch
ctx.Done()is applied:Timeout—engines/extism/compiler/internal/compile/compile.go:49-55.wazero.NewRuntimeConfig()with no.WithCloseOnContextDone(true)—engines/extism/compiler/options.go:111-113,engines/extism/compiler/internal/compile/settings.go:22.In extism go-sdk v1.7.1, close-on-context-done is enabled only when
manifest.Timeout > 0. With neither set,instance.CallWithContext(ctx, ...)(evaluator.go:112) runs to completion regardless ofctx.The public constructor
extism.FromExtismLoader(engines/extism/new.go) exposes no runtime-config option, so public-API callers have no workaround; only code reaching intocompiler.WithRuntimeConfig(wazero.NewRuntimeConfig().WithCloseOnContextDone(true))can opt in.Reproduction (confirmed)
Evalwith an already-cancelled context still ran the module to completion and returnedmap[greeting:Hello, World!]rather than a cancellation error.Impact
High — there is no way to bound or abort WASM execution through the public API. A malicious or buggy guest hangs the caller's goroutine, and timeouts are silently ineffective.
Related defect
engines/extism/evaluator/evaluator.go:114-118: because cancellation never actually interrupts the call, reaching this branch means the guest failed for its own reason whilectxhappened to be cancelled. The real error is then replaced with"execution cancelled: context canceled", discarding the cause. Wrap both errors (%w … %w), or preferctx.Err()only for wazero's exit-code-canceled sentinel.Fix
Default the compile settings'
RuntimeConfigtowazero.NewRuntimeConfig().WithCloseOnContextDone(true)(incompile.WithDefaultCompileSettings,compile.compile, andCompiler.applyDefaults), and/or set a manifestTimeout. Add a test assertingEvalwith an expired context returns promptly with a cancellation error. Consider exposing a runtime-config or timeout option onFromExtismLoader.