Trust boundaries: local agents, plugins, previews, and deployment

OpenDesign's openness is also its security model. The product can combine local files, third-party plugins, powerful coding agents, external providers, and a daemon that serves both UI and API, so the important question is not whether one feature is “safe” in isolation. It is which boundary protects which resource. This chapter separates preview isolation from agent authority, explains what plugin capabilities actually gate, and gives the reader the operational conditions needed to judge a deployment rather than treating local-first as a blanket security guarantee.

A useful diagnosis begins with a symptom: a generated page appears inside a sandboxed preview, and the interface feels contained. That visual containment says something real about the preview frame. It says nothing by itself about the process that generated the page, the files the process can reach, the credentials held by the daemon, or the network interfaces exposed by a public deployment.

flowchart LR User["Browser or CLI user"] --> Daemon["Loopback or authenticated daemon"] Plugin["Plugin source"] --> Gate["Trust and capability gate"] Gate --> Daemon Daemon --> Agent["Selected agent process"] Agent --> Workspace["Project workspace or imported folder"] Daemon --> Preview["Sandboxed preview iframe"] Daemon --> Guard["SSRF and URL policy"] Guard --> External["Provider or connector"] Operator["Operator"] --> Public["Public deployment configuration"] Public --> Daemon

The diagram separates three paths that are easy to merge in conversation: the plugin-to-run path, the agent-to-files path, and the daemon-to-external-services path. A defensible setup must address all three.

A preview can be sandboxed while the agent remains trusted

OpenDesign treats plugin previews as potentially untrusted content. A preview from a GitHub repository or an archive is served through a read-only route and rendered in a restricted iframe. The documented default allows scripts but withholds same-origin access, forms, popups, and downloads unless a first-party preview has a declared reason for an exception. A dedicated content-security policy limits where images, media, styles, scripts, and connections can come from. The preview cannot call the daemon's API, attach authorization headers, read provider credentials, or inspect the project filesystem.

Those controls address a specific threat: the HTML used to show a plugin or artifact should not become a privileged extension of the host application. The path to preview assets is normalized, and the product rejects absolute paths, traversal, symlink escapes, hidden credential files, and oversized resources according to the plugin rules. A restricted plugin can still show a preview because rendering is separated from capability grant. Seeing an example is not the same as authorizing the plugin to stage files or start tools.

The boundary stops at the frame. The plugin may supply instructions that an agent reads during a later run, and the agent may have file, shell, network, or connector authority assigned by its own runtime and by OpenDesign's gates. The preview sandbox does not sandbox that agent process. Nor does a safe iframe prove that the generated artifact is safe to deploy: a page can be visually isolated during review and still contain unwanted behavior once moved into another hosting environment.

This is why the plugin capability model starts with a narrow distinction. A restricted plugin can inject its allowed prompt context, but capabilities such as reading or staging assets, writing files after a run, configuring MCP servers, invoking subprocesses or Bash, making network requests, and calling connectors are separate permissions. The capability vocabulary is declarative, yet the effects are not cosmetic.