diff --git a/examples/wasm-code-sandboxing-go/README.md b/examples/wasm-code-sandboxing-go/README.md new file mode 100644 index 00000000..f1387678 --- /dev/null +++ b/examples/wasm-code-sandboxing-go/README.md @@ -0,0 +1,54 @@ +# WASM-based Code Sandboxing in Go with Monty-Go + +This example demonstrates WASM-based Python code sandboxing using [Monty-Go](https://github.com/fugue-labs/monty-go), a Go library that runs Python code in a WebAssembly sandbox using [wazero](https://github.com/tetratelabs/wazero) (pure Go, zero CGO). + +## Container vs WASM Sandboxing + +E2B and Monty-Go represent two complementary approaches to code sandboxing: + +| | E2B (Container-based) | Monty-Go (WASM-based) | +|---|---|---| +| **Environment** | Full OS with filesystem, network, packages | Minimal Python interpreter in WASM | +| **Startup time** | ~150ms (cloud sandbox) | Sub-millisecond (in-process) | +| **Capabilities** | Install packages, run shell commands, access network | Pure computation, external functions via Go callbacks | +| **Isolation** | VM-level isolation in the cloud | WASM memory sandbox, in-process | +| **Best for** | Complex multi-step code execution, data analysis, system tasks | Lightweight expression eval, formula execution, tight Go integration | + +### When to Use Each + +**Use E2B when you need:** +- Full Python package ecosystem (pandas, numpy, matplotlib) +- File system access, network requests, or shell commands +- Long-running or resource-intensive computations +- Complete OS-level isolation + +**Use Monty-Go when you need:** +- Sub-millisecond startup for high-throughput evaluation +- Embedded Python execution inside a Go service +- Deterministic, resource-limited execution with strict memory/time caps +- Zero external dependencies (no containers, no cloud, no CGO) + +## Setup + +### 1. Install Go + +Ensure you have [Go 1.22+](https://go.dev/dl/) installed. + +### 2. Clone and run + +```bash +cd examples/wasm-code-sandboxing-go +go run main.go +``` + +No API keys, containers, or external services required. + +## How it works + +Monty-Go embeds a Python interpreter compiled to WebAssembly. Each `Execute` call creates an isolated WASM instance with its own memory, so multiple executions cannot interfere with each other. Go functions can be exposed to Python code via callbacks, enabling sandboxed Python to interact with your Go backend. + +## Next steps + +- Combine both approaches: use Monty-Go for fast inline evaluations and E2B for heavy-lift tasks +- See the [Monty-Go documentation](https://github.com/fugue-labs/monty-go) for the full API reference +- See [E2B docs](https://e2b.dev/docs) for cloud sandbox capabilities diff --git a/examples/wasm-code-sandboxing-go/go.mod b/examples/wasm-code-sandboxing-go/go.mod new file mode 100644 index 00000000..52c58ed0 --- /dev/null +++ b/examples/wasm-code-sandboxing-go/go.mod @@ -0,0 +1,10 @@ +module github.com/e2b-dev/e2b-cookbook/examples/wasm-code-sandboxing-go + +go 1.25.1 + +require github.com/fugue-labs/monty-go v0.1.0 + +require ( + github.com/tetratelabs/wazero v1.11.0 // indirect + golang.org/x/sys v0.38.0 // indirect +) diff --git a/examples/wasm-code-sandboxing-go/go.sum b/examples/wasm-code-sandboxing-go/go.sum new file mode 100644 index 00000000..dcf50a48 --- /dev/null +++ b/examples/wasm-code-sandboxing-go/go.sum @@ -0,0 +1,6 @@ +github.com/fugue-labs/monty-go v0.1.0 h1:4N0ztIWWNju2bkGCLg68RKZa/AdsW6pENO1f5WnMBAM= +github.com/fugue-labs/monty-go v0.1.0/go.mod h1:/IEDxFEvHB+vxZCdJTF3pMv6HwSd5LYLthYIH4uI7gg= +github.com/tetratelabs/wazero v1.11.0 h1:+gKemEuKCTevU4d7ZTzlsvgd1uaToIDtlQlmNbwqYhA= +github.com/tetratelabs/wazero v1.11.0/go.mod h1:eV28rsN8Q+xwjogd7f4/Pp4xFxO7uOGbLcD/LzB1wiU= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= diff --git a/examples/wasm-code-sandboxing-go/main.go b/examples/wasm-code-sandboxing-go/main.go new file mode 100644 index 00000000..f2b95a76 --- /dev/null +++ b/examples/wasm-code-sandboxing-go/main.go @@ -0,0 +1,83 @@ +package main + +import ( + "context" + "fmt" + "log" + "time" + + montygo "github.com/fugue-labs/monty-go" +) + +func main() { + // Create a WASM-sandboxed Python runner. + // The WASM module is compiled once and reused across Execute calls. + runner, err := montygo.New() + if err != nil { + log.Fatal(err) + } + defer runner.Close() + + ctx := context.Background() + + // Example 1: Execute Python code with resource limits + result, err := runner.Execute(ctx, + ` +def fibonacci(n): + if n <= 1: + return n + return fibonacci(n-1) + fibonacci(n-2) + +result = [fibonacci(i) for i in range(10)] +result +`, + nil, // no inputs + montygo.WithLimits(montygo.Limits{ + MaxDuration: 5 * time.Second, + MaxMemoryBytes: 10 * 1024 * 1024, // 10MB + MaxRecursionDepth: 100, + }), + ) + if err != nil { + log.Fatal(err) + } + fmt.Printf("Fibonacci sequence: %v\n", result) + + // Example 2: Pass inputs from Go into Python + result2, err := runner.Execute(ctx, + ` +total = sum(values) +f"Processed {len(values)} items, total = {total}" +`, + map[string]any{ + "values": []int{10, 20, 30, 40, 50}, + }, + ) + if err != nil { + log.Fatal(err) + } + fmt.Printf("Result: %v\n", result2) + + // Example 3: Expose Go functions to Python via external function callbacks + result3, err := runner.Execute(ctx, + ` +data = fetch_data("users") +len(data) +`, + nil, + montygo.WithExternalFunc( + func(ctx context.Context, call *montygo.FunctionCall) (any, error) { + // In production, this would call your Go backend, database, or API + return []map[string]any{ + {"name": "Alice", "age": 30}, + {"name": "Bob", "age": 25}, + }, nil + }, + montygo.Func("fetch_data", "endpoint"), + ), + ) + if err != nil { + log.Fatal(err) + } + fmt.Printf("User count: %v\n", result3) +}