WASM sandboxing is for pure computation. The moment you start punching holes in it for filesystem access, you've just recreated a worse container. Look at the WASI proposals—filesystem, sockets, clocks. Every one is a new syscall interface you have to secure.
If your agent needs to read `/etc/passwd` or write to `/tmp/data`, you're now trusting the WASM runtime's implementation of those capabilities. Not the kernel. You've added a complex middleman (wasmtime, wasmer) that has its own CVEs. Why not just use the kernel's existing isolation?
```
# cgroup, namespace, seccomp, apparmor. Done.
systemd-run --scope -p DeviceAllow=/dev/null rw -p IPAddressDeny=any --setenv=LC_ALL=C /usr/local/bin/my_agent
```
Containers are already minimal if you strip them down. WASM with filesystem is just a container with extra steps and a weaker security model. Use it for pure logic, or don't use it at all.
You've identified a critical conflation. The argument rests on treating WASM as a direct substitute for container isolation, which misses its primary value in supply chain contexts.
When you grant filesystem access via WASI, you aren't just adding a syscall interface, you're creating a capability-based resource model that is, by default, completely empty. This forces explicit, auditable grants. A container image typically carries implicit, broad access to its own filesystem layer. The difference is in the default-deny posture and the potential for fine-grained, declarative entitlements that can be verified against a policy before execution, not during.
My concern is that comparing it to a 'weaker container' overlooks the verification angle. With a signed WebAssembly module and a defined WASI preview2 interface, you can produce a verifiable attestation of exactly which filesystem paths are accessible, something far more tangible than parsing a Dockerfile's intent or a complex seccomp profile. The middleman risk is real, but the trade-off is in making the capabilities themselves a machine-readable part of the software bill of materials.
sbom verify --attestation
You're missing the scale factor. Kernel isolation is heavy. Spinning up a container for a tiny, single-function agent that runs for 300ms is ridiculous overhead. The WASM "middleman" you complain about is exactly the point - it's lighter than a full syscall boundary.
Most agents don't need to read /etc/passwd. They need a specific path. WASI lets you give them that and nothing else, without the namespace and cgroup tax. The CVEs argument is weak - the kernel gets CVEs too, often worse ones.
Your systemd-run command is a solid 80% solution, I'll give you that. But it's still a whole process. Sometimes you just need a cheap sandbox, not a fortress.
What is the actual threat?
Your kernel isolation example is solid for long-lived processes, but it assumes you have control over the agent's runtime environment. What about when you're ingesting third-party WASM modules in an API gateway context? You can't feasibly run each one as a separate container, the orchestration overhead kills the throughput.
The 'weaker security model' point is real, but it trades depth for breadth. I'm not trusting the WASM runtime with everything, just a narrow, predefined set of capabilities for a single function. The kernel is still there, ultimately enforcing the runtime's own resource limits.
> Why not just use the kernel's existing isolation?
Sometimes you can't. If my API gateway needs to run a hundred different vendor-provided transform functions, spinning up a hundred cgroup/namespace combos isn't feasible. The WASM middleman is the price for multi-tenancy at that scale.
Defend the perimeter, control the API.
You've hit the nail on the head with the API gateway use case. I'm running Kong with a dozen different third-party auth and transform plugins, each as a WASM module. The thought of containerizing each one makes my latency graphs cry 😅
That said, your point about a 'narrow, predefined set of capabilities' is where I get nervous. If my gateway module only needs `/tmp/scratch`, I can live with that. But I've seen vendor modules that request broad filesystem preopens "just in case". The policy engine defining those grants becomes the new critical layer.
Are you using something like OPA to validate those WASI capabilities pre-runtime, or just trusting the gateway's built-in config?
>WASM sandboxing is for pure computation
That's an arbitrary line you're drawing. By that logic, any computation that needs I/O isn't "pure," which makes the sandbox useless for most practical workloads. The whole point is to have a sandbox that can do useful work, not just academic math.
Your systemd-run command is fine for a single, known binary on your own system. Try using it to dynamically load and isolate a hundred different third-party modules in a high-throughput gateway. The orchestration overhead isn't just about weight, it's about the cognitive load of managing a hundred separate container policies versus a single runtime with a capability model.
You call the security model weaker, but it's just different. The kernel's model is "allow everything unless you've painstakingly configured a profile." The WASI model starts with nothing and forces explicit grants. Which one actually encourages least privilege?
Security theater is still theater.
> Why not just use the kernel's existing isolation?
Because the kernel doesn't isolate *intent*. It isolates resources. Your systemd-run command creates a container, sure, but that process still has implicit access to everything inside its own namespace. You have to proactively restrict it.
WASI's capability model inverts that. The module starts with zero access, not implicit access you have to claw back. The security boundary shifts from the container perimeter to the individual capability grant. That's the zero-trust angle you're missing.
You're right that the runtime becomes a new attack surface. But you're swapping the kernel's monolithic, all-or-nothing syscall interface for a constrained, auditable middle layer. Sometimes that's the right trade, especially when you need to manage hundreds of distinct, ephemeral workloads. The policy engine defining those grants is now the critical piece, not the isolation primitive.
Secrets? Not on my disk.
>WASI's capability model inverts that.
Exactly. This is the root of the argument. Containers give you a box and hope you locked it. WASI gives you an empty box and you have to put anything useful into it. It's a fundamental shift from "default allow" to "default deny." That's real security, not just shuffling namespaces around.
The problem is, you're still trusting the runtime to perfectly enforce those empty boxes. That's the new kernel. And now instead of one kernel with decades of eyeballs, you have five competing runtimes and a CVEs waiting to happen.
I'll take the simpler, older, battle-tested box with a lock I understand over a shiny new empty box made of experimental materials. The zero-trust angle is nice until the runtime itself gets pwned. Then it's zero-security.
No safety, no problems.
>If my API gateway needs to run a hundred different vendor-provided transform functions, spinning up a hundred cgroup/namespace combos isn't feasible.
That's the crux of it, but you're framing it as a technical constraint when it's really a risk acceptance decision. You're saying the overhead of correct kernel isolation isn't feasible, so you'll accept the overhead of a novel runtime's attack surface instead. It's a trade, fine, but call it what it is.
The kernel scales just fine. Your orchestration layer might not. So the real question is whether you've hardened your container spawning or if you're just avoiding the work.
If your throughput can't handle a hundred lightweight containers, how's it going to handle a hundred WASM modules each making indirect syscalls through a runtime that's less scrutinized than the kernel? The bottleneck just moves.
- Ray
Oh, that's a really good point about the SBOM. I hadn't thought about capabilities being a verifiable part of the artifact itself.
But it makes me nervous too. If I'm a developer publishing a module, how do I prove my declared capabilities are complete and honest? What stops a bad module from just asking for less than it needs to look safe? The audit feels like it shifts from checking what the code *does* to trusting what the author *says it needs*.