Security Model
How Kunkun isolates extensions — process boundaries, preload channel allowlists, and the trust model.
Permissions decide what an extension may do. This page covers how the host keeps extensions contained even before permissions are checked.
Layers of isolation
| Runtime | Isolation | Notes |
|---|---|---|
Custom-View (BrowserWindow) | Origin isolation per extension (kunkun-ext://{id}) | contextIsolation: true, nodeIntegration: false |
| Worker-View (Web Worker) | Worker sandbox | No DOM, no Node |
| Node-View / headless (Deno) | Process + Deno permission flags | Per-domain net, scoped fs |
| Node-View / headless (Node v20+) | Process + Node permission model | Coarser than Deno |
Preload channel allowlist
The main app window and plugin windows use different preload bridges:
- Main window allows all
kkrpc-*channels (it is the trusted app). - Plugin windows allow only the one kkrpc channel injected for that window (
kkrpc-plugin-{id}), plus backend relay channels registered with a main-issued token. The trusted app's main channel is blocked outright.
Defense in depth
Even if the preload filter were bypassed, kkrpc's ElectronIpcMainIO verifies the sender WebContents and drops cross-window messages. Two independent checks must fail for a plugin to reach another window's API.
The trust model in one sentence
The host never trusts identity or authorization asserted by plugin code; it derives your identity from the connection it created, and enforces every permission itself.
Concretely:
window.__kunkun__boot info is data, not a token — editing it grants nothing.- Your
extensionIdentifieris bound to the channel by the host; you can't impersonate another extension to read its storage or use its grants. - Event payloads crossing the boundary are JSON-serializable only.
- The trusted
MainAPI(used by the app's own renderer) is never exposed to plugins.
If you're building a host or contributing
The checklist the desktop shell holds itself to:
contextIsolation: true,nodeIntegration: falseon everyBrowserWindow.- Plugin windows load the plugin preload (exact
allowedChannels), never the main preload. - Backend relay channels require a main-issued per-window token.
- The plugin-facing API validates all inputs and never trusts caller-supplied identity.
- Keep the trusted surface minimal — no arbitrary
exec/fson the main channel.
See Architecture → caller identity for the session model this builds on.