0002 – Two plugin runtimes: in process and sandbox container
Status: accepted
Context
Section titled “Context”Plugins range from device drivers with real-time audio (must be fast and closely integrated) to foreign code or code generated by the assistant itself (must not be able to do anything unexpected).
Decision
Section titled “Decision”builtin/trustedplugins run in the core process, but only through a permission-checkedPluginContext.untrustedplugins (all uploaded and all generated ones) run in the sandbox container: own internal network without internet and LAN, read-only,cap_drop: ALL, own UID, rlimits per plugin process. Access to core functions only through a gateway with a plugin-bound token that checks every operation against the granted permissions. HTTP is executed by the core (allowlist, no private targets).- Certain permissions (
devices.provide,devices.control,ai.provide,network.lan, …) are always excluded for untrusted plugins. - Untrusted plugins may register event types in their namespace and run background jobs (at least 60 s apart, at most 5); both are announced to the core, which registers the event types in its catalog.
Alternatives
Section titled “Alternatives”- Everything in process with Python sandboxing (RestrictedPython or similar): cannot be secured reliably in Python.
- One container per plugin: stronger isolation, but the core would need Docker socket access (itself a security risk) and a lot of resources.
- WebAssembly: the Python ecosystem in WASM is still limited.
Consequences
Section titled “Consequences”- Untrusted plugins cannot be device drivers or AI providers.
- Plugins share the sandbox container; rlimits and separate processes limit mutual interference but do not replace a VM (SECURITY.md).