Security¶
chatwire's security model is: gate access at the network layer, use the web UI password as a second layer, and rely on the anti-spam fuse to prevent abuse.
Network access¶
By default the web UI has no authentication — anyone who can reach the URL can read and send messages. The intended posture is:
- LAN only — bind chatwire to
127.0.0.1(default) and don't expose the port externally - Tailscale — expose the Mac via Tailscale; only your devices can reach it
- Cloudflare Access — put chatwire behind a Cloudflare tunnel with an Access policy
Configure the listen address in ~/.chatwire/config.json:
Setting bind to 127.0.0.1 means only requests from the Mac itself can reach chatwire directly. Pair with Tailscale or a reverse proxy for remote access.
Web UI password¶
Set an optional shared password for the web UI:
Settings → Security → Web UI password
Or during first-run setup (Step 4 of the wizard).
Details:
- Single password (not multi-user)
- Stored as PBKDF2-SHA256 in ~/.chatwire/config.json (mode 600)
- Sessions use signed cookies that expire after 30 days (sliding refresh for active sessions)
Forgot your password? Stop the web agent, edit ~/.chatwire/config.json, remove the web.auth block, and restart. No reset flow needed because the file is already protected by your Mac's user account.
# Find and remove the web.auth block:
nano ~/.chatwire/config.json
# Delete the "auth": {...} section under "web"
# Restart the web agent:
launchctl kickstart -k gui/$(id -u)/dev.chatwire.web
Login rate limiting¶
The login endpoint has built-in rate limiting — repeated failed attempts are throttled. This is a minor defense against online brute-force; the main protection should be network-layer access control.
API keys¶
For programmatic access (MCP, scripts, automations), use API keys instead of the session password:
Settings → Security → API Keys → Generate new key
API keys have format cwk_<hex>. Use as a Bearer token:
Keys are scoped:
- read — read conversations and messages
- write — send messages
Revoke a key from Settings → Security → API Keys → click the key → Revoke.
Anti-spam fuse¶
The fuse prevents runaway outbound sends — protecting your iMessage account if the web UI is compromised or an automation rule goes wrong.
Fuse steps¶
| Step | State | What you see |
|---|---|---|
| 0 | Normal | Nothing |
| 1 | Counting | Send count tracked |
| 2 | Soft cooldown | Amber banner, countdown timer |
| 3 | Hard cooldown | Amber banner, longer countdown |
| 4 | Lockout | Red warning bar, compose box locked |
| 5 | Extended lockout | Same, longer cooldown |
| 6 | Permanent lockout | Unlock code required |
Fuse state file¶
The fuse state is stored in ~/.chatwire/fuse_state.json:
Unlocking the fuse¶
At step 4+, a red LockoutTopBanner appears on every page with: - The current fuse step and cooldown duration - A field to enter an unlock code
The unlock code is stored in ~/.chatwire/lockout.json. Access it from the Mac's terminal:
Enter the code in the web UI to reset the fuse to step 0.
To unlock without the web UI:
# Edit fuse_state.json directly:
echo '{"step": 0, "cooldown_until": null}' > ~/.chatwire/fuse_state.json
# Restart the bridge:
launchctl kickstart -k gui/$(id -u)/dev.chatwire.bridge
Configuring fuse thresholds¶
Fuse thresholds are configured in Settings → Anti-spam. The defaults are tuned for normal personal messaging — lower them if you want a stricter guard, raise them if automation rules legitimately send at a higher rate.
Data exposure warning¶
On first launch, chatwire shows a dismissable modal explaining which data it accesses:
- Reads
~/Library/Messages/chat.db(your full iMessage history) - Reads Contacts.app (for name resolution)
- Sends messages via Messages.app
The modal is not shown again after you click I understand. If you want to see it again, clear ~/.chatwire/read_state.db.
Privacy¶
- Zero telemetry — chatwire sends no analytics, crash reports, or usage data. No third-party SDKs.
- Data stays on your Mac — your messages, contacts, and
chat.dbnever leave your machine unless you explicitly configure a relay (Telegram, ntfy, webhook, etc.) - Update check — once per day, chatwire fetches
api.github.com/repos/allenbina/chatwire/releases/latestto surface new-version notices. Disable by settingUPDATE_CHECK_REPO=""in the launchd agent's environment.
See the privacy policy for full details.
Security audit status¶
chatwire is in active development and has not undergone a formal third-party security audit. Use it on a trusted network or behind Cloudflare Access / Tailscale. Security improvements are tracked in the GitHub issues.