Security Model

How CloudCLI UI isolates plugins with frontend sandboxing, server process restrictions, secret handling, and path traversal protection.

Plugins run with significant privileges. The host mitigates risk through multiple layers of isolation.

Trust Model

Plugins are trusted code. Installing a plugin is equivalent to running someone's Node.js code on your machine. Only install plugins from sources you trust.

Frontend Isolation

Your frontend module receives only the api object. It cannot access:

  • The host's React state or component tree
  • Authentication tokens or session cookies
  • Other plugins' state or API
  • localStorage or sessionStorage of the host app

Frontend modules are loaded via dynamic import() from a Blob URL. Your code runs in the same origin as the host but cannot access the host's module graph. All backend communication must go through api.rpc(), and a plugin can only call its own server.

Server Process Isolation

Plugin server processes receive only four environment variables:

VariablePurpose
PATHSystem PATH
HOMEUser home directory
NODE_ENVNode environment
PLUGIN_NAMEPlugin identifier

All other env vars from the host are stripped. Each plugin server runs in its own Node.js process with isolated memory, CPU, and file descriptors. Servers must bind to 127.0.0.1 only.

Lifecycle control:

  • 10-second startup timeout prevents hung initialization
  • SIGTERM + 5-second grace period for graceful shutdown
  • SIGKILL fallback for unresponsive processes

Secret Management

Secrets live in ~/.claude-code-ui/plugins.json. They are injected as HTTP headers on each RPC request (x-plugin-secret-<key>), meaning they travel over localhost only, are per-request (not in process memory), and each plugin only receives its own secrets. Updated secrets take effect immediately.

Limitations: secrets are not encrypted at rest, not rotated automatically, and not validated by the host.

Installation Security

  • Only https:// and git@ URLs accepted
  • Shallow clones (--depth 1)
  • Directory names validated against /^[a-zA-Z0-9_.-]+$/
  • Manifest validated on install and every scan
  • npm install uses --production --ignore-scripts (no lifecycle scripts)

Asset Serving Security

Path traversal protection ensures served assets stay within the plugin directory. The host resolves the requested path, verifies it's within bounds, and rejects escape attempts. Plugin names are validated against /^[a-zA-Z0-9_-]+$/.

Recommendations

Do: validate RPC inputs, bind to 127.0.0.1, handle errors without leaking paths, document required secrets, keep dependencies minimal.

Don't: store secrets in code, bind to 0.0.0.0, shell out with unsanitized input, access files outside the project path, log secrets.

Known Limitations

LimitationImpact
Module-type plugins share the host's DOMCould modify host UI
No CPU/memory limitsCould consume excessive resources
No filesystem sandboxingCan access any user-accessible file
No network restrictionsCan make any network call
Secrets stored in plaintextReadable by anyone with filesystem access

Last updated March 9, 2026