Privacy & security

wigolo's privacy model is structural, not a policy promise: the software runs on your machine, stores on your disk, and has no vendor backend to send anything to.

Everything stays local

The whole state of a wigolo install lives in the data dir (~/.wigolo by default):

PathContents
wigolo.dbThe knowledge cache: pages, search results, full-text + vector indexes.
jobs.dbWatch jobs.
model cachesThe on-device embedding and ranking models (two directories, created at init/warmup).
config.jsonNon-secret settings (secrets are excluded by design — see below).
keys/Encrypted credential files, only when the OS keychain isn't available.
plugins/Installed plugins.
skills/receipts.jsonThe skills install ledger.
shell-historyInteractive shell history.
telemetry/Opt-in local event files — absent unless you enable telemetry.
searxng/The optional legacy aggregator sidecar, only if you opted into that backend.
daemon-admin.tokenPer-process admin-route token (owner-only file permissions, rotated each daemon start).

rm -rf ~/.wigolo erases all of it. wigolo config --storage shows what's using space.

Network egress

wigolo makes outbound connections only to:

  1. The search engines and websites your queries target — that's the product working.
  2. The LLM provider you configure, if you configure one. Keyless local setups (including WIGOLO_LOCAL_LLM=auto against a local model server) never leave the machine for synthesis.
  3. A telemetry endpoint you set yourself — see below; there is no default.

Component downloads (browser engine, models) fetch from their public distribution sources during init/warmup or first use. There is no license check, no update phone-home, no account.

Telemetry: off, local, yours

Off by default. If you opt in with WIGOLO_TELEMETRY=1, events are appended to a local NDJSON file (~/.wigolo/telemetry/events-YYYYMMDD.ndjson) — nothing is transmitted. A network POST happens only if you additionally set WIGOLO_TELEMETRY_ENDPOINT to a URL of your own; wigolo ships no vendor endpoint to send to. wigolo doctor always shows the current telemetry state.

Credentials

Secrets never sit in plaintext on disk:

  • LLM API keys go to the OS keychain. Where no keychain is available, they're written as AES-256-GCM-encrypted files under ~/.wigolo/keys/. init reads a key only from the WIGOLO_LLM_API_KEY env var — never from a flag, so it can't leak into shell history or process listings.
  • Proxy credentials (and the URLs for opt-in solver/reader services): userinfo is split off and stored in the keychain; only the credential-free URL is persisted to config.json.
  • wigolo config --export excludes secrets, so a shared settings file can't leak keys.
  • The REST bearer token supports WIGOLO_API_TOKEN_FILE so deployments can mount it as a secret instead of an env var visible in process inspection.

Serve-mode hardening

The HTTP daemon assumes the network is hostile:

  • Fail-closed bind gate — a non-loopback bind with no token refuses to start; open remote access requires a named override flag. (Details.)
  • Bearer auth on the REST + MCP surface when a token is configured; /health alone stays open for probes.
  • DNS-rebinding guard — requests whose Host header isn't loopback (or the configured bind host) are rejected, so a malicious page resolving its domain to 127.0.0.1 gets a 403, not your daemon.
  • Browser-origin guard — any request carrying an Origin header is rejected on the MCP and admin routes before token checking, so web pages can't probe token validity.
  • Loopback source is never trusted as auth — tunnels deliver remote traffic from 127.0.0.1, so authentication is the token, not the source address.
  • Slow-client timeouts, body caps, concurrency caps bound resource use (limits).

SSRF guards

URL-taking surfaces refuse targets that resolve to private or loopback address space:

  • fetch / crawl / every URL-bearing REST route — private targets blocked unless you opt in for local dev (WIGOLO_FETCH_ALLOW_PRIVATE=true).
  • watch webhook destinations — a watch notification can't be pointed at your internal network.
  • Remote-exposed daemons additionally refuse loopback-literal targets outright, so a remote caller can't use wigolo to probe services on its own host (posture).

Responsible disclosure

Please don't open public issues for vulnerabilities. Report privately via GitHub's "Report a vulnerability" on the repository's Security tab — the process, scope, and response expectations are in SECURITY.md.

← Docs index · Back to start: Getting started

Edit this page on GitHub