Security model
Boundaries
- The server exposes only threads you switched on, only from the history start you set, to only the access keys you created, each with its own thread scope and limits. Everything else returns "no such thread," including in search.
- Message text passes through a deterministic credential filter before it leaves the database (on by default).
- The listener binds to loopback and, with Tailscale, the Mac's Tailscale address. It never listens on Wi-Fi or Ethernet addresses. Public modes connect to loopback through a tunnel process that dies with the app.
- Access keys are 192-bit random, compared in constant time, stored as SHA-256 hashes. 10 failed attempts lock a source out for 15 minutes; a global bucket caps throughput at 20 requests/second. Daily caps answer 429.
- Requests that don't complete in 15 seconds are dropped; bodies over 2 MB are rejected.
- No network calls originate from the app except the optional update check and tunnel processes you start.
- Every request is logged (key, source, tool, thread, count, status), never its content.
Known limits
- Anyone holding a valid key who can reach the endpoint can read what that key is scoped to. Treat keys like passwords; revoke on suspicion.
- Public tunnels put the endpoint on the internet. Keys and rate limits are then the only protection. Prefer Tailscale; if public, prefer Cloudflare Tunnel with Cloudflare Access in front.
- The credential filter is pattern-based. It catches known key formats and labelled values, not every possible secret.
- The agent you connect sees what you allow. Blue Text Relay limits the blast radius; it can't make the agent trustworthy.
Verify it yourself
Every release ships its full source. Build it, read it, diff it against the DMG. The license allows exactly that.
Reporting
Email security@bluetextrelay.com. Please don't post vulnerabilities publicly before we've had a chance to fix them. We aim to acknowledge within 2 business days.