Plugin Security and Trust
August 3, 2026 ยท View on GitHub
Synergy validates what it can enforce and states the rest explicitly.
Before Code Import
Installation and discovery read only generated metadata. They verify manifest/API versions, canonical identity, contribution shape, capability references, package paths, artifact hashes, registry metadata, and signatures before executable runtime or UI code is imported.
Source plugin.json is forbidden because it would create a second declaration path. The installed manifest must be generated by plugin-kit and match packaged artifacts.
Approval
Approval covers publisher identity and the structured access grant. A handler cannot request a Host Service that is absent from the manifest and grant. The complete manifest hash still binds signatures, artifact integrity, and the short approval-review transaction, but ordinary metadata or implementation changes are not treated as new user access.
The permissions hash binds capability constraints, access-bearing contribution requirements, operation exposure, and trusted UI presence through the shared public integrity contract. It identifies the grant for integrity and comparison; it is not a low/medium/high score.
Approval review is server-authoritative. Configured plugins use GET /api/plugins/:pluginId/approval-review to fetch the current review. Submission uses POST /api/plugins/approve with only the canonical target and opaque reviewToken; Web and CLI clients never send manifests, capabilities, source specs, or paths as approval evidence. The reviewToken binds the canonical target, current manifest hash, and permissions hash. If the artifact changes before submit, the server returns stale_review with a refreshed review and performs no writes.
Plugins disabled for approval keep their canonical identity, version, access summary, contribution summary, and disabled status. User-facing surfaces label that state as Needs approval.
Official registry plugins with official: true and a valid reviewed signer install under policy without an extra confirmation. Other sources receive one concise source-and-access confirmation on first install. Updates continue automatically for the same source/signer when access is equal or narrower. Broader access, a signer/source change, or an unknown constraint change requires confirmation. Signature or integrity failure blocks the package and cannot be overridden.
Capabilities govern Synergy Host Services. They do not pretend to block direct OS filesystem or network calls made by an external plugin process. Review external plugin code and provenance accordingly.
Runtime Boundary
External server code runs in a separate process. This provides crash, timeout, cancellation, and cleanup isolation. It is not an OS sandbox: Synergy does not claim container, seccomp, filesystem virtualization, or network isolation for plugins.
Only trusted built-ins may use inProcess. There is no worker runtime fallback.
The runtime handshake must match protocol version, generation, and the exact executable handler set declared by the manifest. The host selects the protocol in activation and the Runner echoes that selection in ready; it does not replace the running host's selection with a newer constant read from mutable development files. Requests carry generation and are rejected if their result arrives after another generation becomes active. Additive API4 Host Services, hooks, and contributions do not change the transport envelope and therefore do not change the runtime protocol version.
Host Services and Scope
Every Host Service call is bound to the invocation's plugin, Scope, optional Session, actor, and cancellation signal. Workspace paths must remain inside the active Scope. Credentials use a plugin-scoped store and must not enter config, logs, UI bundles, diagnostics, or browser storage.
Agent-only services such as delegated tasks and tool invocation require agent/session/message identity and still pass through Synergy's ordinary visibility, control-profile, permission, and enforcement paths.
asset.write does not expose an arbitrary host filesystem handle: context.asset.create() transfers bytes to the host and returns a host-owned attachment. shell.execute exposes only argv-based context.shell.run() and still passes through the active control profile, permission system, sandbox, cancellation, and timeout. settings.write can replace only the invoking plugin's scoped settings.
Declarative MCP contributions do not execute through the plugin process. The host validates every strict local or remote server declaration before replacing the plugin's complete MCP server set atomically. Local commands remain argv arrays; remote URLs are limited to parseable http or https endpoints. Global config names may shadow an unqualified plugin server name, but the qualified ${pluginId}::${contributionId} identity remains stable for resolution, OAuth state, reload, and cleanup.
Trusted UI
Trusted components execute in the App context after approval. plugin-kit and the host enforce the shared Solid build contract, named exports, UI API major, package hash, and generation-specific asset URL. This protects lifecycle and consistency; it is not an iframe sandbox.
The UI receives bound operations, scoped events, and explicit host actions. It does not receive raw credentials, a server URL, or an unrestricted SDK client.
Review Checklist
- Confirm repository, author, release artifact, signature, and registry metadata agree.
- Confirm
definePlugin().idis stable and unique. - Review every requested Host Service and constraint, especially writes, credentials, delegated tasks, tool invocation, and trusted UI.
- Confirm executable handler IDs exactly match generated contributions.
- Confirm input/output/event schemas reject unexpected data.
- Confirm workspace paths and plugin-owned data paths cannot escape their intended roots.
- Confirm lifecycle migrations are idempotent and uninstall behavior is explicit.
- Confirm errors, logs, settings, and events do not expose secrets.
- Confirm long work uses plugin-owned handles/events instead of blocking an operation indefinitely.
- Run build, runtime discovery validation, tests, pack inspection, and signature verification before distribution.