feat(worker): fail closed on virtual_machine execution class without kata#199
feat(worker): fail closed on virtual_machine execution class without kata#199devin-ai-integration[bot] wants to merge 1 commit into
Conversation
…kata The Kubernetes provider advertised the VirtualMachine worker capability only for the kata isolation profile with a RuntimeClass, but validate_runtime_profile never re-checked execution_class at provision time. Add a provider-boundary check mirroring the APEX/gVisor one so a virtual_machine spec on a non-kata / RuntimeClass-less worker is rejected rather than provisioned, completing the fail-closed VM-class profile (SW-2). Co-Authored-By: Jonathan Haas <jonathan@0xHaas.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
| if spec.execution_class == ExecutionClass::VirtualMachine { | ||
| anyhow::ensure!( | ||
| self.isolation_profile == IsolationProfile::Kata | ||
| && self | ||
| .runtime_class_name | ||
| .as_deref() | ||
| .is_some_and(|name| !name.trim().is_empty()), | ||
| "virtual_machine execution_class requires the kata isolation profile and a RuntimeClass" | ||
| ); | ||
| } |
There was a problem hiding this comment.
📝 Info: VM-class provider check consistent with capability advertisement
The new fail-closed check at crates/sandboxwich-worker/src/provider.rs:620-629 requires IsolationProfile::Kata plus a nonempty runtime_class_name for ExecutionClass::VirtualMachine. This is the exact inverse of the capability advertisement at crates/sandboxwich-worker/src/provider.rs:4877-4887, which pushes WorkerCapability::VirtualMachine only when runtime_class_name.is_some() and the profile is Kata. Since with_runtime_class_name already normalizes empty/whitespace strings to None, the is_some_and(|name| !name.trim().is_empty()) guard is equivalent to the advertisement's is_some() check, so the provider boundary and placement-time matching stay in agreement. validate_runtime_profile is invoked on all provision/fork/apply paths (provider.rs:939, provider.rs:3643, provider.rs:3687, provider.rs:5036), so the check is not bypassable.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Thanks — agreed, that's the intent: the provider-boundary check is the deliberate inverse of the capability advertisement, and since with_runtime_class_name normalizes empty/whitespace to None, is_some_and(|n| !n.trim().is_empty()) is equivalent to the advertisement's is_some(). The trim().is_empty() guard is defensive against a future path that sets runtime_class_name without going through the normalizing setter. No change needed.
Summary
Closes a fail-closed gap in the VM-class isolation contract (SW-2). The worker already advertises the
VirtualMachinecapability only forIsolationProfile::Kata+ a nonemptyRuntimeClass, and placement matches jobs to workers byrequired_execution_class. But the provider itself never re-checkedexecution_classat provision time — only the APEX/gVisor case was guarded invalidate_runtime_profile. So avirtual_machinespec reaching a mis-scoped/developmentprovider would render and provision instead of being rejected.This adds the missing provider-boundary check, mirroring the existing APEX one:
Defense-in-depth: VM-class (hostile-workload) provisioning now fails closed at the provider boundary rather than relying solely on placement-time capability matching.
Behavior unchanged for
development_container/sandboxed_containerand for correctly-configured Kata workers.Test
New
provider::tests::virtual_machine_execution_class_requires_kata_and_runtime_class:kata-qemuRuntimeClass → provisions, pod carriesruntimeClassName: kata-qemu.Ran locally with the pinned toolchain (
cargo +1.95.0):cargo fmt --check— cleancargo clippy -p sandboxwich-worker --all-targets -- -D warnings— cleancargo test --workspace— all pass (163 worker tests incl. the new one). Postgres-backed contract tests were not run (SANDBOXWICH_TEST_POSTGRES_URLunset); they self-skip.Link to Devin session: https://app.devin.ai/sessions/794b5e0853624962b67878f01835857c
Requested by: @haasonsaas