Security & Threat Model
Last updated: July 7, 2026
Every claim below is sourced from Daisy's code — you can read it yourself at github.com/smallbricktory/daisy-local. File references are given throughout so any of this can be re-audited.
Daisy is a local-first meeting recorder, transcriber, and summarizer. The security posture follows from that: your recordings, transcripts, and summaries live on your disk, in open formats, and leave your machine only through paths you explicitly configure. Credentials are encrypted at rest. The app is fully functional offline.
1. Architecture and trust boundaries

Trust boundaries:
- WebView ↔ Rust core. The UI cannot reach the network or the filesystem
directly; every operation goes through Tauri commands. CSP:
connect-src ipc: http://ipc.localhostonly — even injected script in the WebView has no network path (tauri.conf.json). - App ↔ disk. Secrets cross this boundary only inside the encrypted vault envelope. Meeting content crosses it in plaintext by design (§3).
- Machine ↔ network. Nothing containing meeting content crosses this boundary unless you configure a cloud provider or a webhook integration (§4).
2. Data classification
| Class | Examples | At rest | Rationale |
|---|---|---|---|
| Credentials | Provider API keys, webhook auth secrets, calendar feed URLs, per-install signing seed, MCP token, voiceprint embeddings | Encrypted (vault) | Dangerous in motion; encryption must travel with the file (backups, sync) |
| Meeting content | Audio, transcripts, summaries, chapters, in-call chat, search index | Plaintext, open formats | Your data; grep-able, sync-able, outlives the app. Protect with full-disk encryption (§7) |
| Configuration | Settings, tags, prompts, workflows, contacts | Plaintext | Needed before vault unlock; contains no secrets |
| License / install identity | Install ID, license key, signed validity stamp | Plaintext | Needed before vault unlock; low-value, seat-limited, server-revocable |
3. Data at rest
All paths are relative to the profile directory (your platform's data dir).
Encrypted — the vault. keys.vault.json holds provider API keys, integration
webhook auth values, subscribed calendar feed URLs, the per-install signing seed,
the MCP bearer token, and voiceprint embeddings. calendar/events.json is an
encrypted cache derived from those feed URLs.
The vault uses AES-256-GCM with a key derived by Argon2id (64 MiB, 3 iterations, 4 lanes), a fresh random salt and nonce on every write. A wrong passphrase is an authentication failure, never garbage output.
- Passphrase mode (default): minimum 22 characters and a "strong" strength score, enforced at creation. There is no recovery — a lost passphrase means re-entering your keys, never lost recordings.
- Machine mode (opt-in): the key derives from the OS machine ID and the vault auto-unlocks at startup. This protects vault copies that leave the machine (backups, synced folders) but not against someone with access to the running machine. Choose passphrase mode if your threat model includes other local users.
Plaintext — meeting content lives under sessions/<id>/: audio, transcript,
summary, chapters, in-call chat, and the local semantic-search index. This is your
data in open formats — see Vault & profile.
Plaintext — configuration (settings, tags, prompts, workflows, contacts, integration history) contains no secrets; it's needed before the vault unlocks.
Logs are local only, rotated daily, deleted after 7 days. Transcript and summary text is never written to logs; window names are salted-hashed.
Telemetry: none. No analytics, crash reporters, or tracking calls exist anywhere in the app.
4. What leaves your machine, and when
Offline, Daisy records, transcribes (local Whisper), summarizes (local LLM), and searches with zero egress. This is the complete inventory.
Automatic — never any meeting content
| Call | Destination | Carries | Gate |
|---|---|---|---|
| Update check | daisy.smbr.app/updates/… |
A version string | On launch + every 6 h, only if the auto-update-check setting is on; notify-only (the app never downloads or installs updates itself); fail-silent |
| License check-in | daisy.smbr.app/api/license/refresh |
License key, install ID | On launch + a 6 h beat; throttled to ~1/day server-side; fail-silent |
| Calendar refresh | Your ICS/webcal URLs | The fetch itself | Only if you subscribed a calendar |
User-configured or user-clicked — content only by your choice
| Feature | Destination | Carries |
|---|---|---|
| Cloud summaries / chat / analysis | Anthropic, or any OpenAI-compatible endpoint (incl. local LM Studio / Ollama) | Transcript text + your prompts (your key) |
| License activate / deactivate | daisy.smbr.app/api/activate |
License key, install ID |
| Webhook integrations | Your URL (Zapier / n8n / your endpoint) | The payloads you select per destination — see Integrations |
| Model download | huggingface.co |
Nothing personal (you click download) |
| Help / source links | www.daisylocal.app, the source repo |
Nothing — opens in your browser |
Daisy Cloud — the daisy.smbr.app/api/gateway/… endpoint in the code is an
internal-only service tied to the license key. When a license is entitled,
Daisy proxies the AI step (transcript text, never audio) to Anthropic and
OpenAI using our own keys — Ed25519-signed per install, with no stealable API
key. It's an internal convenience, not part of a normal install;
regular users bring a local model or their own key.
Every remote call uses TLS. The only plaintext HTTP in the app is loopback (your local AI servers, the MCP server). The UI performs zero direct HTTP — every call above happens in the Rust core behind an explicit command, and the CSP gives injected WebView script no network path.
5. Threat model
Assumptions. Your OS and user account are not compromised (Daisy is an app, not an anti-malware boundary — software running as you can read what you can read). TLS/PKI works.
| Threat | Scenario | Mitigation |
|---|---|---|
| Information disclosure | Profile folder leaves the machine (cloud backup, Syncthing, sold laptop, support zip) | Credentials stay AES-256-GCM ciphertext wherever the files travel; meeting content is plaintext by design — see §6 |
| Information disclosure | Another local user reads the vault file | Passphrase mode: Argon2id makes offline guessing expensive; a strength policy blocks weak passphrases |
| Information disclosure | Data leaks into diagnostics | No telemetry; logs carry no transcript text; window names hashed |
| Spoofing | Stolen "API key" for the gateway | No bearer credential exists — a per-install Ed25519 signature over method, path, timestamp, nonce, and body hash; replay-limited |
| Tampering | Malicious "update" | Updater is notify-only; you download from the website in your browser. Windows builds are Authenticode-signed, macOS builds Developer ID-signed (both to Apexis Solutions Inc.) |
| Tampering | License forgery | Validity stamps are Ed25519-signed by the vendor, verified against a key pinned in the binary |
| Elevation of privilege | Web content escapes the UI | Strict CSP (no network, frames, or objects); zero direct HTTP from the frontend; all privileged ops are explicit commands |
| Elevation of privilege | A local process abuses the MCP port | Loopback bind + vault-held bearer token; off by default; write access separately gated |
Explicitly out of scope: a compromised OS or root-level malware / memory scraping of the running, unlocked app (no desktop app can defend this); machine- mode vault against a local attacker (a documented tradeoff); a configured cloud provider's own data handling (their retention applies to what you send them — the local default sends nothing); physical theft of a powered-on, logged-in machine.
6. Residual risks
- Meeting content is plaintext on disk. Deliberate: encrypting it would let a lost passphrase destroy your entire history, complicate crash recovery, and break grep/sync of your own data — while adding little against the realistic attacker (anything running as you reads it anyway while the app is open). The mitigation is full-disk encryption (§7), which covers the real at-rest threat: a stolen or discarded disk.
- The vault protects copies, not the running machine. An attacker with persistent code execution as you can wait for unlock.
- Model downloads are not checksum-pinned. Integrity rests on TLS and the host.
- Webhooks trust your endpoint. Payloads go to the URL you configure.
7. What you should do
- Turn on full-disk encryption — BitLocker (Windows), FileVault (macOS), LUKS (Linux). This is the intended protection for meeting content at rest.
- Prefer passphrase mode for the vault on shared or managed machines.
- Treat the profile folder like the recordings it contains when backing up or syncing — the vault file is safe anywhere; transcripts are as private as the folder you put them in.
- Point webhooks only at endpoints you control or trust.
Running Daisy where PHI is involved? See Configuring Daisy for HIPAA and PHI.
8. Reporting a vulnerability
Please report suspected vulnerabilities privately by email to support@daisylocal.app rather than in a public issue. Include steps to reproduce and the build SHA from Settings → About. We aim to acknowledge within 72 hours.