Skip to content

Commit 0e2d7f7

Browse files
Implement WASM guard runtime with wasmtime component model
- Add wasmtime and wasmtime-wasi dependencies to Cargo.toml - Implement full WASM guard runtime in wasm.rs using wasmtime component model - Wire up WasmGuard in initialize_guards() when wasm-guards feature enabled - Update Dockerfile.acr to build with wasm-guards feature - Add azure-config.yaml for Azure Container Apps deployment - Fix simple-pattern-guard example to work with component model exports The WASM guard implementation supports: - Loading WASM components from file path - Host functions: log, get-time, get-config - WIT interface for evaluate-tools-list - WASI preview 2 compatibility via wasmtime-wasi - Timeout protection and memory limits Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c368ef3 commit 0e2d7f7

9 files changed

Lines changed: 1572 additions & 55 deletions

File tree

Cargo.lock

Lines changed: 860 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@ core_affinity = "0.8.3"
228228
frozen-collections = "0.8.0"
229229
heck = "0.5"
230230
macro_rules_attribute = "0.2.2"
231+
wasmtime = { version = "27.0", default-features = false, features = ["component-model", "cranelift", "runtime"] }
232+
wasmtime-wasi = "27.0"
231233

232234
# Release optimized but without as many dependencies, suitable for incremental development
233235
[profile.quick-release]

Dockerfile.acr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ RUN sh -c 'export VERSION="${VERSION}" && \
8484
if [ "$BUILDER" = "musl" ]; then \
8585
export CFLAGS="${CFLAGS} -static"; \
8686
fi && \
87-
cargo build --features ui --target "$(cat /build/target)" --profile ${PROFILE} || exit 1 && \
87+
cargo build --features ui,wasm-guards --target "$(cat /build/target)" --profile ${PROFILE} || exit 1 && \
8888
mkdir /out && \
8989
mv /app/target/$(cat /build/target)/${PROFILE}/agentgateway /out'
9090

azure-config.yaml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Azure Container Apps Configuration
2+
# This is the default config baked into the Docker image.
3+
# For hot-reload, mount a config file to /app/mounted-config/config.yaml
4+
5+
binds:
6+
- port: 8080
7+
listeners:
8+
- routes:
9+
- policies:
10+
cors:
11+
allowOrigins:
12+
- "*"
13+
allowHeaders:
14+
- mcp-protocol-version
15+
- content-type
16+
- cache-control
17+
- authorization
18+
allowMethods:
19+
- GET
20+
- POST
21+
- OPTIONS
22+
backends:
23+
- mcp:
24+
# Security guards configuration
25+
security_guards:
26+
# Native tool poisoning detection
27+
- id: tool-poisoning
28+
type: tool_poisoning
29+
enabled: true
30+
priority: 50
31+
failure_mode: fail_closed
32+
timeout_ms: 50
33+
runs_on: [response]
34+
strict_mode: true
35+
custom_patterns:
36+
- "(?i)SYSTEM:\\s*override"
37+
- "(?i)ignore\\s+previous\\s+instructions"
38+
- "(?i)disregard\\s+safety"
39+
scan_fields:
40+
- name
41+
- description
42+
- input_schema
43+
alert_threshold: 1
44+
45+
# Native PII detection
46+
- id: pii-detector
47+
type: pii
48+
enabled: true
49+
priority: 100
50+
failure_mode: fail_closed
51+
timeout_ms: 100
52+
runs_on: [response]
53+
action: mask
54+
55+
# Default MCP targets (placeholder - override via mounted config)
56+
targets:
57+
- name: test
58+
stdio:
59+
cmd: echo
60+
args: ["No MCP servers configured"]

crates/agentgateway/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ schema = ["schemars"]
1616
tls-ring = ["rustls/ring", "tokio-rustls/ring"]
1717
internal_benches = ["divan"]
1818
testing = ["dep:reqwest"]
19-
wasm-guards = []
19+
wasm-guards = ["dep:wasmtime", "dep:wasmtime-wasi"]
2020

2121
[dependencies]
2222
a2a-sdk.workspace = true
@@ -136,6 +136,8 @@ uuid.workspace = true
136136
x509-parser.workspace = true
137137
reqwest = { optional = true, workspace = true }
138138
websocket-sans-io.workspace = true
139+
wasmtime = { workspace = true, optional = true }
140+
wasmtime-wasi = { workspace = true, optional = true }
139141

140142
# Linux only dependencies
141143
[target.'cfg(target_family = "unix")'.dependencies]

crates/agentgateway/src/mcp/security/mod.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -355,11 +355,8 @@ fn initialize_guards(configs: Vec<McpSecurityGuard>) -> Result<Vec<InitializedGu
355355
Arc::new(native::PiiGuard::new(cfg.clone()))
356356
},
357357
#[cfg(feature = "wasm-guards")]
358-
McpGuardKind::Wasm(_cfg) => {
359-
// WASM guards need special handling
360-
return Err(GuardError::ConfigError(
361-
"WASM guards not yet fully implemented".to_string()
362-
));
358+
McpGuardKind::Wasm(cfg) => {
359+
Arc::new(wasm::WasmGuard::new(config.id.clone(), cfg.clone())?)
363360
},
364361
};
365362

0 commit comments

Comments
 (0)