Sandboxed Plugins¶
Sandboxed plugins are designed for untrusted or experimental code. They run in a separate subprocess with restricted imports, filesystem access, and resource limits. Unlike Trusted plugins, they are isolated from the main application's memory and services.
Prerequisites¶
- Xcore Installation
- C++ Scanner Build (Highly Recommended)
- Plugin Anatomy understood
Key Concepts¶
Total Isolation¶
A Sandboxed plugin does not have access to the PluginContext. It cannot directly use self.get_service() or emit events on the global bus. Instead, it acts as a "pure actor" that receives a payload and returns a JSON response.
graph LR
K[Xcore Kernel] -- IPC (JSON) --> W[Sandbox Worker]
W -- handle() --> P[Sandboxed Plugin]
P -- result --> W
W -- IPC (JSON) --> K
Security Layers¶
- AST Scanning: Before loading, Xcore scans the code for forbidden imports (
os,subprocess,ctypes, etc.) and dangerous builtins. - Filesystem Guard: Intercepts
open()andpathlibcalls. By default, only thedata/directory is writable. - Resource Limits: Enforces Memory (RSS/Data) and CPU time limits via Linux
resourcemodule. - Namespace Isolation: Uses a custom
sys.meta_pathhook to ensure the plugin can only import its own local files or whitelisted standard modules.
Practical Guide¶
1. Implementation¶
Since you don't inherit from TrustedBase, your plugin class just needs to implement the handle method.
2. Manifest Configuration¶
You must explicitly declare the execution_mode and resource limits in plugin.yaml.
| plugin.yaml | |
|---|---|
Security Restrictions¶
Forbidden Modules¶
The following modules (and many others) are blocked by default:
- os, sys, subprocess
- socket, ssl, http, urllib, requests, httpx, aiohttp
- ctypes, cffi, mmap
- threading, multiprocessing
- pickle, marshal
Forbidden Builtins & Attributes¶
exec,eval,compile,input__subclasses__,__mro__,__globals__,__builtins__
API Reference¶
Sandboxed plugins are managed by the SandboxProcessManager.
| Action | Result |
|---|---|
ping |
Internal action used for health checks. Returns {"status": "ok", "pong": true}. |
shutdown |
Gracefully stops the worker process. |
| custom | Any action handled by your handle() method. |
Common Errors & Pitfalls¶
PermissionError: [sandbox] BLOCKED
This occurs if your plugin tries to import a forbidden module or access a restricted file.
Check: Look at the stack trace in the logs to see exactly where the violation occurred.
IPCTimeoutError
If your handle method takes longer than resources.timeout_seconds, the supervisor will kill the call and return an error.
Fix: Optimize your code or increase the timeout in plugin.yaml.
DiskQuotaExceeded
The data/ directory is monitored. If it exceeds max_disk_mb, further calls will be blocked.
Fix: Delete old files in data/ or increase the quota.
Best Practices¶
Stateless Design
Treat your sandboxed plugins as stateless functions. While you can write to data/, assume the process can be restarted at any time by the supervisor.
Local Imports
You can import any .py file located within your plugin's src/ directory. They are automatically added to your isolated namespace.
See Also¶
- Security & Sandboxing
- Deep dive into the
FilesystemGuardandASTScannerimplementation. - Permissions & Policies
- How to request specific permissions in the manifest.