Docs

Security and privacy

The trust model, the known limits, where your data goes, and a checklist for your private network.

Drover is for one trusted operator on machines and networks that the operator controls. It is not a multi-tenant service.

Supported boundary

Use Drover on:

  • localhost on one machine,
  • a trusted private LAN,
  • a private Tailscale network whose members you control.

Do not use Tailscale Funnel, a public reverse proxy or a public port forward. The relay protocol can create sessions and carries terminal streams.

The listeners do not provide TLS. With a plain HTTP address, traffic to the hub is not encrypted by HTTPS. A tailnet encrypts traffic between its members.

Authentication

  • Each phone and each host has its own bearer credential, from a pairing code.
  • The hub stores only a SHA-256 hash of each credential.
  • A pairing code exists only in the memory of the hub. It is single use.
  • A device code expires after ten minutes. A host code expires after fifteen minutes.
  • The hub blocks a source after five failed redemptions in one minute.
  • MCP requires the same credentials as the HTTP API. See MCP authentication.

If you lose a phone, revoke its credential. The change applies on the next request:

drover-server credentials list
drover-server credentials revoke <credential-id>

Known limits

  • A host credential is not bound to a host identity. A host credential can act as any registered host. Enroll only machines that you control. See issue 13.
  • The shared token is on by default. Set [auth] legacy_token_enabled = false after each device and host has paired.
  • No users or roles. Each paired device and registered host is in one trust domain. Credential scopes are the only access control.
  • No sandbox. An agent runs with the account and file permissions of the host daemon.
  • A device or host credential gives shell access to each registered host.
  • MCP is loopback only. No protected remote transport is available.

What Drover stores

The context store can contain prompts, responses, repository paths, diffs, tool calls and terminal output.

Data Location
Configuration, credential hashes, shared token ~/.drover/, sensitive files with mode 0600
Fleet state, events, summaries, profile Your PostgreSQL control store
Analytical facts Your DuckLake catalog and Parquet files, if selected
Host spool A local DuckDB file on each host
Phone credential The iOS Keychain

There is no Drover account and no Drover-hosted store. The project cannot delete or recover your data.

When data leaves your machines

When Data Destination
A harness runs The data that the harness sends The model provider of that harness
Summaries are enabled Transcript text Anthropic
Embeddings use a remote endpoint Text to embed The endpoint you configure
Push notifications are enabled A device token, and alerts with a short response preview Apple
You add a host Events and session traffic Your own machines
The update check is on A request for the latest release GitHub

A push alert can appear on a lock screen.

Portable profile

Each profile item has one tier:

  • General: visible to each agent with a credential.
  • Trusted: visible to agents with a trusted profile credential.
  • Private: visible to you only.

An agent sees a count of the items it cannot read, and nothing else about them.

A Markdown import sets each item to private by default. Headings such as health, finance or address keep a section private. The import also keeps text private if it looks like an address, an amount, a phone number or an email. These checks are heuristics. Review each item before you change its tier.

Agents can propose profile changes. You approve each proposal, and you can revert it.

iOS app

The app requests three permissions:

  • The camera, to scan a pairing code.
  • The local network, to connect to your hub.
  • Notifications, if you want alerts.

The app connects directly to your hub. Sign Out removes the credential and the local data from the phone, and asks the hub to revoke the credential. If the hub is not available, revoke the credential on the hub.

Before you bind beyond localhost

  1. Make sure that a request to /harness/hosts without a credential returns 401.
  2. Make sure that a request with a credential works through the private address.
  3. Restrict the port with the host firewall or a Tailscale policy.
  4. Make sure that no Funnel, public reverse proxy or public port forward is active.
  5. On a laptop that joins networks you do not trust, bind one private address, not 0.0.0.0.
  6. After you remove a host, revoke its credential. If the shared token is enabled, replace it.

Report a vulnerability

Do not open a public issue. Follow SECURITY.md. Only the latest release receives security fixes.

For the full analysis, see the threat model and the privacy notes.

This page is a summary. The reference is docs/security.md.