feat: WebAssembly plugin support with end-to-end host invocation#65
Open
monshri wants to merge 23 commits into
Open
feat: WebAssembly plugin support with end-to-end host invocation#65monshri wants to merge 23 commits into
monshri wants to merge 23 commits into
Conversation
monshri
marked this pull request as draft
June 9, 2026 18:27
monshri
marked this pull request as ready for review
June 9, 2026 18:56
monshri
force-pushed
the
feat/plugin-wasm-e2e
branch
from
June 9, 2026 19:23
51aeb57 to
7fde6ca
Compare
Contributor
Author
|
@araujof @terylt Few things to discuss on current implementation: 1. Raw Credentials - Completely Blocked
2. SecurityExtension - TruncatedOnly 4 of 8 fields are available in WASM: Available:
Missing:
Impact: WASM plugins cannot make workload-aware or client-aware authorization decisions 3. Extension Slots - Only 4 of 13 AvailableAvailable in WASM:
Missing from WASM:
To discussFor 1, we can discuss if we want to keep it as-is or not |
monshri
marked this pull request as draft
June 18, 2026 13:34
monshri
force-pushed
the
feat/plugin-wasm-e2e
branch
from
July 2, 2026 23:38
888ec5d to
51b3347
Compare
Introduces the WASM plugin sandbox system: cpex-wasm-plugin (guest-side cdylib targeting wasm32-wasip2) and cpex-wasm-host (host-side runtime using wasmtime with sandbox policy enforcement, resource limits, and network filtering). Signed-off-by: Shriti Priya <shritip@ibm.com>
… functionality in wasm compilation Signed-off-by: Shriti Priya <shritip@ibm.com>
Signed-off-by: Shriti Priya <shritip@ibm.com>
Signed-off-by: Shriti Priya <shritip@ibm.com>
Signed-off-by: Shriti Priya <shritip@ibm.com>
Signed-off-by: Shriti Priya <shritip@ibm.com>
Signed-off-by: Shriti Priya <shritip@ibm.com>
monshri
force-pushed
the
feat/plugin-wasm-e2e
branch
from
July 2, 2026 23:52
51b3347 to
18988db
Compare
…ation Fix WIT keyword conflict (%resource escape), add feature-gated plugin SDK supporting multiple plugins from a single crate, and implement three WASM demos: CMF pipeline, identity resolution, and capabilities isolation with extension modification across the sandbox boundary.
…ing WIT import, per-invocation resource limits, and full payload coverage tests Signed-off-by: Shriti Priya <shritip@ibm.com>
…e test target, and suppress warnings Signed-off-by: Shriti Priya <shritip@ibm.com>
Signed-off-by: Shriti Priya <shritip@ibm.com>
monshri
marked this pull request as ready for review
July 21, 2026 18:28
Signed-off-by: Shriti Priya <shritip@ibm.com>
Signed-off-by: Shriti Priya <shritip@ibm.com>
Signed-off-by: Shriti Priya <shritip@ibm.com>
Signed-off-by: Shriti Priya <shritip@ibm.com>
Signed-off-by: Shriti Priya <shritip@ibm.com>
Signed-off-by: Shriti Priya <shritip@ibm.com>
Signed-off-by: Shriti Priya <shritip@ibm.com>
Signed-off-by: Shriti Priya <shritip@ibm.com>
Signed-off-by: Shriti Priya <shritip@ibm.com>
This was
linked to
issues
Jul 22, 2026
Contributor
|
Thanks for this PR @monshri ! Can you please map the new crate into the cpex facade crate and the release workflow? Also, including a doc pages and examples where you can demonstrate the sandbox in action would be cool. Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
WASM Plugin End-to-End Support
Resolves #21 & #24
Summary
This PR introduces a complete WebAssembly (WASM) plugin sandbox system for the CPEX framework. It enables running untrusted or third-party plugins inside isolated Wasmtime sandboxes while maintaining full compatibility with the existing native plugin pipeline.
Scope: 2 new crates, ~20,400 lines added across 73 files, 46+ integration/E2E tests, full benchmarking suite, and comprehensive documentation.
Motivation
The CPEX plugin framework currently runs all plugins natively with full host access. This creates a security boundary problem for third-party or community plugins that should not have unrestricted filesystem, network, or memory access. WASM sandboxing provides:
HookHandler<H>trait andPluginManager.invoke()API as native pluginsArchitecture
Key design decisions:
HookHandler<H>and register viaPluginFactory, soPluginManager.invoke()works identically for native and WASM pluginscpex-core— tokio/runtime deps made optional so cpex-core compiles towasm32-wasip2(guest SDK depends on it withdefault-features = false)HookPayload::Customvariant for user-defined typeshandle_hookcall; WASM linear memory persists across calls (enablesOnceLockstate patterns)#[serde(skip)]on token fields ensures raw credentials never cross the sandbox boundaryNew Crates
crates/cpex-wasm-host/— Host RuntimeThe host-side runtime that loads, sandboxes, and invokes WASM plugin binaries. Integrates with
cpex-core'sPluginManagervia thePluginFactorytrait.src/factory.rsWasmPluginFactory+WasmBridgeHandler— bridges PluginManager to sandboxessrc/sandbox_manager.rsSharedEngine,SandboxManager, network policy, host-logging WIT importsrc/conversions.rssrc/policy_loader.rsSandboxPolicystruct, WASI context builder from YAML configsrc/payload_registry.rsDependencies: wasmtime 45.0 (component-model + async), wasmtime-wasi, wasmtime-wasi-http, cpex-core, tokio, serde, tracing
crates/cpex-wasm-plugin/— Guest SDKThe plugin-author SDK. Compiled as
cdylibtowasm32-wasip2target.src/lib.rsregister_wasm_plugin!macro,cpex_log!macro,__block_onsync executorsrc/conversions.rssrc/plugins/Dependencies: wit-bindgen 0.57, cpex-core (default-features = false), serde, async-trait, chrono, zeroize
WIT Interface Contract
Package:
cpex:plugin(656 lines incrates/cpex-wasm-host/wit/world.wit)export handle-hook: func( hook-name: string, payload: hook-payload, extensions: extensions, ctx: plugin-context ) -> hook-result;Payload variant types:
cmf— structured field-by-field CMF MessagePayloadidentity— structured IdentityPayloaddelegation— structured DelegationPayloadcustom— JSON bytes with type discriminator (user-defined payloads)Imports: WASI P2 (io, clocks, http, filesystem, sockets, random, cli) + custom
host-logginginterfaceSecurity Model (5-Layer Defense-in-Depth)
Sandbox enforcement (per-invocation):
Changes to
cpex-coredefault = ["runtime"]withruntimefeature guarding tokio/tokio-util/arc-swap/cpex-orchestration — enables compilation forwasm32-wasip2executor,factory,manager,registry,visitorgated behind#[cfg(feature = "runtime")]WasmSerializablePayload(type discriminator + JSON serialize/deserialize) withimpl_wasm_payload!macroMessagePayload,IdentityPayload,DelegationPayloadall implementWasmSerializablePayloadPlugin Demos
Capability-Gated Plugins (CMF payload)
identity_checker.rsheader_injector.rsaudit_logger.rstoken_attenuator.rsnoop.rsCustom Payload Plugins (ToolInvokePayload)
tool_invoke_checker.rspii_guard.rsremote_authz.rsOnceLock)audit_logger_custom.rscompute_bench.rsSandbox Test Fixtures
fs_test.rsnet_test.rsenv_test.rsTests
test_security_enforcement.rstest_custom_payload_pipeline.rstest_sandbox_isolation.rstest_sandbox_network.rstest_sandbox_env.rstest_policy_loader.rsTotal: ~49 tests
Benchmarking
Criterion-based benchmarks in
crates/cpex-wasm-host/benchmarking/:Conclusion: For typical CPEX usage (2-4 plugin calls per LLM request at ~200ms), WASM overhead is 20-40us total — 0.01-0.02% of request latency.
Includes
plot_results.pyfor generating comparison charts and a step-by-stepREADME.md.Configuration
YAML-based plugin configuration with sandbox policies:
Build System
Workspace changes:
cpex-wasm-hostadded to workspace memberscpex-wasm-pluginexcluded (compiled separately forwasm32-wasip2target)Makefile targets (both crates):
make build-all-plugins— build all WASM binariesmake build-test-plugins— build sandbox test fixturesmake build-bench-plugins— build benchmark pluginsmake test— clean, rebuild, run all testsmake bench-all— full benchmark suite + chart generationmake run-demos— build and run example binariesmake clean-all— remove all artifactsDocumentation
docs/specs/cpex-wasm-spec.mdcrates/cpex-wasm-host/README.mdcrates/cpex-wasm-plugin/README.mdcrates/cpex-wasm-host/benchmarking/README.mdHow to Test
Files Changed (73 files)
Click to expand full file list
New — Host Runtime (
crates/cpex-wasm-host/)Cargo.tomlMakefilesrc/lib.rssrc/factory.rssrc/sandbox_manager.rssrc/conversions.rssrc/policy_loader.rssrc/payload_registry.rswit/world.witwit/deps/cli.witwit/deps/clocks.witwit/deps/filesystem.witwit/deps/http.witwit/deps/io.witwit/deps/random.witwit/deps/sockets.witconfig/config.yamlconfig/config_capabilities.yamlconfig/config_plugin_demo.yamltests/test_security_enforcement.rstests/test_custom_payload_pipeline.rstests/test_sandbox_isolation.rstests/test_sandbox_network.rstests/test_sandbox_env.rstests/test_policy_loader.rsbenchmarking/invocation.rsbenchmarking/comprehensive.rsbenchmarking/plot_results.pybenchmarking/performance_comparison.pngbenchmarking/README.mdexamples/wasm_plugin_demo.rsexamples/wasm_capabilities_demo.rsREADME.mdNew — Guest SDK (
crates/cpex-wasm-plugin/)Cargo.tomlMakefilesrc/lib.rssrc/conversions.rssrc/plugins/mod.rssrc/plugins/identity_checker.rssrc/plugins/header_injector.rssrc/plugins/audit_logger.rssrc/plugins/token_attenuator.rssrc/plugins/noop.rssrc/plugins/tool_invoke_checker.rssrc/plugins/pii_guard.rssrc/plugins/remote_authz.rssrc/plugins/audit_logger_custom.rssrc/plugins/compute_bench.rssrc/plugins/fs_test.rssrc/plugins/net_test.rssrc/plugins/env_test.rsREADME.mdNew — Documentation
docs/specs/cpex-wasm-spec.mdModified — Core
Cargo.toml(workspace)crates/cpex-core/Cargo.tomlcrates/cpex-core/src/lib.rscrates/cpex-core/src/hooks/mod.rscrates/cpex-core/src/hooks/payload.rscrates/cpex-core/src/cmf/message.rscrates/cpex-core/src/identity/payload.rscrates/cpex-core/src/delegation/payload.rscrates/cpex-core/src/config.rsModified — Build/Config
.gitignoreBreaking Changes
None. The feature is entirely additive:
cpex-corechanges are behind a feature flag that defaults tooncpex-wasm-host) is an optional workspace memberFuture Work
.wasmbinaries)