Security & permissions
Plugins are Python and run inside the desktop app, so the platform defends users in layers. Two of those layers are things you interact with directly as an author: declaring permissions and passing the scanner.
Declare what you need (permissions)
Section titled “Declare what you need (permissions)”Your plugin.json declares the sensitive capabilities your code uses:
{ "manifest": 1, "id": "govee_light", "name": "Govee Light", "version": "1.0.0", "entry": "govee_light.py", "permissions": ["network:openapi.api.govee.com"]}| Permission | Grants | Examples |
|---|---|---|
network |
Outbound HTTP / sockets. Add :host to scope it. |
requests, urllib, socket, websockets |
subprocess |
Launch external programs / shell | subprocess, os.system, os.startfile |
filesystem |
Read/write files outside your plugin folder | open(..., "w"), shutil |
native |
Native OS APIs — very powerful | ctypes, Win32, COM, winreg, pycaw |
input |
Synthesize keystrokes / mouse | pynput, keyboard |
gui |
Open your own windows/dialogs | custom Qt dialogs |
Plugins with no permissions field keep the older “prompt on first use”
behavior for backwards compatibility. New plugins should always declare — the
scaffolder adds an empty "permissions": [] for you to fill in.
Scan before you ship (mixlar-sdk scan)
Section titled “Scan before you ship (mixlar-sdk scan)”mixlar-sdk scanStatic analysis (no code is executed) reports the capabilities your code
touches and flags risky patterns — shell-out, eval/exec, obfuscated
exec(base64…), native calls — and tells you when your code uses a capability
you forgot to declare:
[!] capabilities used but NOT declared in permissions (the app will block these at runtime): network Add them to plugin.json → "permissions": [ … ]mixlar-sdk validate runs the same check, mixlar-sdk publish scans and warns
before anything leaves your machine, and the registry’s CI re-scans before
signing — refusing to sign a plugin that uses undeclared capabilities or trips
a high-risk pattern.
The defense layers
Section titled “The defense layers”Strongest first:
- Signature pinning — only ed25519-signed-by-Mixlar plugins auto-trust (see Signing & trust).
- Review before signing — community submissions are reviewed (or come from a trusted author) before they’re signed and listed (see Publishing).
- Least-privilege permissions — the runtime ceiling above.
- Default-deny loading — unverified packages don’t load without an explicit, account-gated “Trust & Load”.
- Quarantine — a remote kill-list for bad plugins.
- The developer agreement — the no-malware attestation required to publish.
Process isolation
Section titled “Process isolation”For an even stronger boundary, the SDK ships a subprocess sandbox that runs a plugin in a separate process with the capability enforcer installed before the plugin is imported — so undeclared use is blocked and a crash or hang can’t take the app down:
from mixlar import sandboxresult = sandbox.run_isolated("path/to/plugin", permissions=["network"])print(result.ok, result.note, result.violations)Today this covers plugins whose runtime is self-contained (device / network / native logic). Plugins that build their settings UI with the app’s Qt objects, or reach into the running app object, still run in-process — isolating those needs a UI/app-API bridge over IPC, which is the next increment. Until then they’re guarded by the same enforcer applied per-plugin (least privilege) — the security win without the compatibility break.
Checklist
Section titled “Checklist”- Declare every capability your code uses in
permissions, scoped tightly. mixlar-sdk scanis clean — no undeclared capabilities, no high-risk hits.- You don’t
eval/execdecoded data, and you don’t shell out unless you truly needsubprocess. - Secrets come from plugin settings, never hard-coded.