Plugin security
The v1 model assumes plugins are your own: written by your team, released from repositories you control.
What is enforced
Admin only. Adding or removing sources, uploading, installing, updating, enabling and uninstalling all go through the admin middleware. The CLI (
<app> plugin …) needs shell access to the host, which is already admin-equivalent.Transport and size. Remote sources must be HTTPS (plain http only for localhost). Zips are capped at 100 MB, downloaded to a temp dir, verified, then moved into place.
Two hash layers.
zip_sha256from the index is checked before extraction; the binarysha256inplugin.jsonis checked after.Signatures. ed25519 over
zip_sha256(index) and over the binary hash (manifest). Required when the source pins a publisher key or the host setsWICK_PLUGIN_REQUIRE_SIGNATURE=1; extra trusted keys come fromWICK_PLUGIN_PUBKEY(comma-separated). Pin the key for private GitHub sources, so a compromised GitHub account cannot slip in a release.PAT handling. Stored encrypted, sent only to the GitHub API host, never to URLs that appear inside an index.
Process limits. Each plugin is its own process with a scrubbed environment and optional rlimits:
WICK_PLUGIN_RLIMIT_AS_MB,WICK_PLUGIN_RLIMIT_CPU_SEC,WICK_PLUGIN_RLIMIT_NOFILE.Sockets. Tool/service sockets are created
0600in a0700run dir, so theX-Wick-User-*headers the host injects cannot be forged from another local user; browser-suppliedX-Wick-*headers are stripped.Tool webhook identity.
X-Wick-Token-User-*(withX-Wick-Token-User-Source=pat,ssoorsystem) is set only after the host verified the credential.For wick's SSO JWT (
X-Wick-User),audis NOT the safeguard. Any approved user who registers anssoconnector may pick its audience, so a connector pointing at an outside server with audience = wick's host would make wick hand that server tokens "for wick". wick therefore:- mints every token with a
wick_urlclaim — the URL it is actually sent to, set by wick and not editable; - accepts a token only when
wick_urlis on one of wick's own hosts (from server config: the base URL's host, or loopback on wick's own listen port; never the request'sHostheader) and at the called tool's/tools/{key}or a path under it. A token sent elsewhere, or minted for another tool, is refused; - refuses to save or mint for an
ssoconnector whose audience names wick while its URL is not wick; - caps a token's lifetime at 15 minutes (clamped at mint, refused at save, rejected at verify), since the system identity has no user to revoke;
- verifies against a key cached in memory, so a forged header never costs a database round-trip.
The subject must be an approved user, checked per request.
system:wickis passed on as the system identity, runs no Host API call as a user, and must be treated as read-only by the plugin.TokenUser()does not return it.- mints every token with a
Service tokens. Route tokens are stored hashed and can be rotated or revoked; the callback token
WICK_PLUGIN_TOKENis scoped to the plugin'sCallbackScopesand revocable.Host API. A plugin calling back into wick is limited to the scopes in its manifest's
host_scopes;rest.*,db.*,connectors.executeandconfig.read_secretalso need an exacthost_resourcesdeclaration (no declaration, no access), anddb.*,rest.writeandconfig.read_secretare off until an admin allows them. Calls run as the triggering user or the owner of the plugin'swick_pat— never as a synthetic admin — and are audited for 7 days. Admins block scopes or single items, block all, or revoke a plugin on Plugins → Host access. See Host API.Audit. Every install, update, upload and source change is logged with actor, source, key, old → new version and
zip_sha256.No silent updates.
auto_updateis off unless enabled per source.
What is NOT guarded yet
A plugin runs as the same OS user as wick. It can read whatever that user can read, open any network connection, and start processes. Before accepting plugins from third parties you would need, at least:
- a separate OS user (or systemd
DynamicUser+ProtectHome), - permissions declared in the manifest (allowed hosts, data dir) and enforced,
- a network allowlist,
- tool UIs served from a separate origin (iframe) instead of the wick origin,
- a visible "third-party" label in the UI.
Until then, install only plugins whose source you trust as much as wick itself.