HarborHarbor
DocumentationGuidesPlugins
Reference

Security Model

Credential vault, sandbox isolation, OAuth trust boundaries.

Harbor's job is to hold credentials so your agents don't have to. This page documents the trust boundaries, the encryption story, and what you should never put where.

Trust boundaries

BoundaryWhat can crossWhat can't
Agent ↔ Harbor (MCP)MCP frames over HTTPS with an OAuth bearer tokenPlugin credentials. The agent never sees Linear / GitHub / Slack tokens.
Harbor ↔ PluginOne decrypted credential, for one upstream call, brieflyPersistent token reuse outside the invoker scope.
Isolate ↔ Workspaceplugins.*, orbit.*, sand.* bindingsRaw filesystem, process env, other workspaces, arbitrary fetch()
sand.* ↔ User machineCurated CLI namespaces (git, gh, wrangler, …)General shell access, arbitrary local binaries
Workspace ↔ WorkspaceNothingEverything. Each workspace is fully isolated in D1, KV, R2.

Credential vault

OAuth tokens, API keys, service-account JSONs are stored encrypted in the workspace credential vault.

  • Cloud: AES-GCM with a per-workspace data key, derived from a master key in Cloudflare Secrets Manager. The decrypted value lives in memory for the lifetime of one plugin invoke and is zeroized after.
  • OSS: AES-GCM at rest in .harbor/credentials.enc, keyed by the HARBOR_LOCAL_CREDENTIAL_KEY env var on the host. The key never hits disk. If you rotate it, existing credentials become unreadable and need to be re-issued.

Open source self-hosters: HARBOR_LOCAL_CREDENTIAL_KEY is the entire auth boundary. Anyone with that env var on the machine has the vault. Treat it like an SSH private key.

OAuth flow

  1. User clicks "Connect" in the dashboard or starts OAuth through an SDK/admin flow
  2. Harbor redirects to the upstream OAuth provider (Linear, GitHub, …)
  3. User consents in their own browser
  4. Provider redirects back to Harbor's loopback callback (OSS) or hosted callback (Cloud)
  5. Harbor exchanges the code for tokens
  6. Tokens encrypted into the vault, plugin source flips to ready

The agent never participates in the OAuth flow. It can ask Harbor to start the flow (hrbr.auth.start()) and Harbor opens the user's browser, but the consent + the token issuance happen between the user and the upstream provider.

Sandboxed execution

hrbr exec and every Function handler run inside a cloud isolate. The isolate has:

  • plugins.* — namespaces typed by tool schemas
  • orbit.* — workspace primitives (storage / cache / db / ai / tools / socket)
  • sand.* — bridges to the original caller's machine via the local hrbr daemon (Cloud + caller has the local CLI installed and authenticated)
  • step.* — durable-execution atoms

The isolate does not have:

  • fetch() to arbitrary URLs (only the plugin invoker can call upstreams)
  • Filesystem access
  • Process env vars
  • Reflection into Harbor internals
  • Other workspaces' state

Output is capped at 1 MB per run. Memory at 128 MB per isolate. Wall time 30 s for sync exec, plan-dependent for Workflows.

What never to store where

StorageEncrypted?Workspace-readable?OK to put
Credential vaultYes (AES-GCM)No (vault is server-only)Tokens, keys, secrets
orbit.storageEncryption at rest (R2 default-managed key)YesReports, artifacts, public reads
orbit.cacheEncryption at rest (KV default-managed key)YesShort-lived non-secret state
orbit.dbEncryption at rest (D1 default-managed key)YesStructured non-secret records
Run input/outputEncryption at restYes (workspace members)Inputs + return values without secrets

Don't put OAuth tokens, API keys, or PII into orbit.storage / orbit.cache / orbit.db. They are workspace-readable. The meta-skill harbor-orbit encodes this rule.

Audit trail

Every workspace action is captured in the activity log:

  • Plugin install / connect / disconnect / refresh
  • Member added / removed / role-changed
  • Function / App / Skill published or disabled
  • Run started, completed, failed, cancelled

The activity log is workspace-readable but immutable from the dashboard UI. Owners can export the log via /audit API or the dashboard.

Data retention

ClassCloud retentionOSS
Trace + spansPlan-dependent (7d Hobby → 1y Enterprise)Until you delete .harbor/
Artifacts (orbit.storage)Plan-dependentUntil you delete
Cache (orbit.cache)TTL per keyTTL per key
Audit log1 yearUntil you delete
Vault credentialsUntil you disconnect the pluginUntil you remove the source

Reporting a security issue

Open a private security advisory at github.com/zonko-ai/harbor/security/advisories.