Kunkun
Concepts

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

RuntimeIsolationNotes
Custom-View (BrowserWindow)Origin isolation per extension (kunkun-ext://{id})contextIsolation: true, nodeIntegration: false
Worker-View (Web Worker)Worker sandboxNo DOM, no Node
Node-View / headless (Deno)Process + Deno permission flagsPer-domain net, scoped fs
Node-View / headless (Node v20+)Process + Node permission modelCoarser 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 extensionIdentifier is 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: false on every BrowserWindow.
  • 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/fs on the main channel.

See Architecture → caller identity for the session model this builds on.

On this page