Skip to content

bug: Extism ignores context cancellation/timeout during WASM execution #155

Description

@robbyt

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 Timeoutengines/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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions