Sandboxed isn't safe
When I introduced afmpeg, one phrase did a lot of heavy lifting: safely process untrusted media. The FFmpeg inside is compiled to WebAssembly and run in a sandbox with:
- no host filesystem
- no network
- no environment
Feed it a hostile file and the worst it can do is fail. That was the pitch.
An external security review read that pitch, then asked a better question than I had: fail taking how much of the host with it? Two different questions wearing one word "Sandboxed" answers one of them: what can it reach? And on that score afmpeg was solid. The guest sees an in-memory filesystem it was handed and nothing else. A malicious file that manages to run code inside the guest has, for all its scheming, broken into a padded room:
- No door
- No window
- Nothing worth taking
But there's a second question the word "safe" smuggles in without telling you: how much can it take? Here afmpeg had no answer at all, and that was the review's headline finding, one I'd commissioned and then made a point of verifying against the code rather than taking on trust. The runtime set no memory limit. None. A wasm32 guest can grow its linear memory towards 4 GB, and a crafted media file is only too happy to help it get there: declare a 65535ร65535 video in the header and libavcodec, doing exactly the job you asked of it, tries to allocate the buffers those dimensions demand. Inside the sandbox. Paid for by the host. So the guest can't read your files, can't phone home, can't escape... and can still get your Go process OOM-killed by the kernel. I'd sandboxed the code execution and said nothing whatsoever about the resource bill. My padded room, it turned out, was drawing its air from the rest of the building, and I hadn't thought to check.
The second finding was the same disease with a different clock: nothing bounded how long an invocation could run. So a pathological decode loop, handed a caller using a background context, would sit on the runtime's lock forever. Not a crash. A wedge. (There was a third one too, minor: some missing type guards in the engine's job-spec parsing, defence-in-depth against a caller the design already trusts. Fixed in the engine for completeness.)
Ceilings, on by default
The fix (`0f20c
Comments
No comments yet. Start the discussion.