Security overview
Security is collie's first requirement: the phone can drive every agent on your machine, so collied treats every request as hostile until proven otherwise. This page is a summary. The threat model covers each threat, its mitigations and what remains.
Network
- Tailnet only.
colliedaccepts connections only through its embedded Tailscale node, on one port. A test asserts it opens no kernel TCP listener. - Whois gate. Every connection is checked with Tailscale whois before anything else. The peer must be untagged, not shared in from another tailnet, owned by the collie owner, and a paired phone whose node still belongs to the user it was paired with. Authorization is checked again before every message, and revoking a phone cuts its live sessions.
- Mutual TLS. Inside the tunnel, the phone pins the machine's TLS key from the pairing QR code, and
colliedpins the phone's key, which lives in the Secure Enclave. A copied Tailscale node key, or a node injected by a compromised control plane, gets no session.
Pairing
A pairing needs the QR code shown by collied pair and your y on the machine. The window lasts 120 seconds and the first attempt closes it.
What the phone can do
collied accepts a fixed list of requests and rejects anything else before reading it. herdr's privileged methods cannot be reached from the phone.
- Approvals carry a one-time nonce and a fingerprint of the prompt on screen.
colliedre-reads the screen and answers only if the fingerprint still matches. - Apple Watch decisions are off by default, need the watch unlocked and on your wrist, and go through the iPhone's same checks.
- Terminals are off unless
collied.tomlturns them on. Each unlock is signed by a second Secure Enclave key after Face ID or the passcode, for one terminal and 5 minutes, and audited without the command text. - Attachments are size-capped, checksummed, stored privately and deleted after 24 hours.
Notifications
The visible part of an alert says which agent is blocked and where. The command is encrypted end to end (ChaCha20-Poly1305) under a key generated on the phone. Apple still sees agent and workspace names, pull request numbers and their status (such as "CI failed on #123" or "PR #123 merged"), opaque IDs and timing.
Secrets on the machine
- macOS: the APNs key is in the login Keychain, readable without a prompt only by the Developer ID signed
collied. - Linux: it is a systemd user credential, encrypted with the host key and sealed to the TPM2 when one is usable, with a file readable only by you as the fallback. Any process running as your user can decrypt it.
Your part
- Keep the tailnet policy tight, and check the login name when you pair.
- When a phone is lost, revoke it with
collied peers revokeand remove its node in the Tailscale admin console. See Revocation. - Revoke a machine's APNs key in the Apple Developer portal if that machine is compromised.