Plugin security

Embed
Preview of the card
<a href="https://forumulate.com/p/watchtower/docs/plugins-security"><img src="https://forumulate.com/api/public/orgs/watchtower/spaces/docs/pages/d79a3735-e8ca-4b5f-afab-e30857f5a05b/social-card.svg?v=3e7ae33eec8b" alt="Plugin security" width="600" height="315"></a>
  • Supply chain. Install needs ManageSecurity. The tarball must carry a detached Ed25519 signature over its SHA-256 from one of the organization's trusted publisher keys (PUT /v1/orgs/{org}/plugin-trust), or the organization must set allow_unsigned (default off). Unsigned installs are audited as plugin.install_unsigned. The SHA-256 is recorded; an update is a new version. The runner verifies the SHA-256 and signature again before it starts any code.

  • Sandbox. One process per plugin, started through the runner's --sandbox wrapper that sets CPU, address-space and file-descriptor limits (Linux/macOS setrlimit; a job object on Windows). The plugin gets no inherited environment, only WT_EGRESS_URL.

  • Network. The plugin reaches the network only through the egress proxy at WT_EGRESS_URL (/<http|https>/<host>/<path>). Hosts outside egress_hosts are 403; the connect-time IP is checked against the SSRF rules; redirects are not followed. Secrets named in secret_refs are added to configured headers by the proxy, replacing any value the plugin sets, so plugin code never sees them.

  • Failure. A crash or a hung call (30 s) kills the process; restarts back off 1 s, 2 s, 4 s ... up to 1 min. Health: GET /v1/orgs/{org}/plugins/{id}/health.

  • Scope. Filters apply to notification and workflow payloads only, never the ingest path. A plugin enabled in one project answers no other project's queries (404).

  • Limits. RLIMIT_AS is not enforced by macOS; run the runner on Linux in production.

Updated