Skip to content

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.

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.

Terminal window
mixlar-sdk scan

Static 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.

Strongest first:

  1. Signature pinning — only ed25519-signed-by-Mixlar plugins auto-trust (see Signing & trust).
  2. Review before signing — community submissions are reviewed (or come from a trusted author) before they’re signed and listed (see Publishing).
  3. Least-privilege permissions — the runtime ceiling above.
  4. Default-deny loading — unverified packages don’t load without an explicit, account-gated “Trust & Load”.
  5. Quarantine — a remote kill-list for bad plugins.
  6. The developer agreement — the no-malware attestation required to publish.

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 sandbox
result = 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.

  1. Declare every capability your code uses in permissions, scoped tightly.
  2. mixlar-sdk scan is clean — no undeclared capabilities, no high-risk hits.
  3. You don’t eval/exec decoded data, and you don’t shell out unless you truly need subprocess.
  4. Secrets come from plugin settings, never hard-coded.