Security
A tool that tells you when a terminal job needs you, and lets you answer from your phone, has to be built so that a mistake or a breach on our side cannot reach your machine. This page is the plain-language version of SECURITY.md, which has the details and the tests behind each claim.
What we assume
An attacker who controls our server and database completely: reading every row, injecting messages, and serving any key they like.
What they can still do
- Hold back or delay messages, so a notification can be late or never arrive.
- See the metadata the server needs to route things: which app, its state (working, blocked, done…), timestamps, your host labels, device names and public keys, and the length of each message.
- Show you a false "X is blocked" line: those routing fields are not signed. They cannot forge the message text.
- Serve you modified web app code. The app is delivered by the server it is protecting you from; see the limits below.
What they cannot do
- Read your messages, commands or working directories. The helper encrypts them on your machine to the devices you paired. The server stores ciphertext.
- Change a message or move it to another record. The helper signs every message and binds it to its session, path and revision; your device checks the signature against the key it pinned when you paired.
- Add a device you did not approve. Pairing shows the same six words on the host and on the device. If a server swaps keys, the words differ and pairing is refused.
- Type into your terminal. The helper types only keys for an option it offered itself, for one specific prompt, and only if the answer is signed by a device in its own local list of paired devices. The keys never leave your machine.
How an answer is checked, on your machine
Before typing anything the helper verifies the signature and the device, that the prompt is still waiting, that you have not already typed an answer yourself, that nobody answered it first, that the answer is fresh and not replayed, and that it names an offered option. Any failure types nothing.
Notifications
A push contains a generic line and some IDs. The message text is decrypted on your phone by the app's service worker, and only if its signature checks out. Once shown, it sits in your phone's notification history; set lock-screen previews to "never" if that matters to you. Push services (Google, Apple, Mozilla, Microsoft) learn that a push happened, when, and its size.
The helper and its installer
- Releases are built in public by a GitHub Actions workflow. Each release has a SHA-256 checksum file, signed keylessly with cosign using the workflow's identity.
- The installer script downloads the release for your platform, checks the checksum and refuses to install on a mismatch. If
cosignis installed it also verifies the signature. It installs to~/.local/binand never uses sudo. - The script is served at /install.sh; read it before you run it. Be aware that, like any
curl | sh, trust in it rests on this site and on the repository.
On the service
- HTTPS only, with HSTS, a strict content security policy, no framing, and an Origin check on the live connection.
- Sign-in, device-code and pairing endpoints are rate limited.
- Payments are handled by Stripe. We never see card numbers.
Known limits
- The web app code comes from the server. A compromised server could ship code that misuses your device's keys while the app is open. End-to-end encryption protects your data at rest and against database leaks, not against a malicious frontend.
- You can still be rushed into approving something dangerous. Beckon proves who answered, not whether the answer was wise. Read the message first.
- Any paired device can answer any prompt on a host that trusts it. There is no second factor, so keep your phone locked and revoke lost devices from Settings.
- There is no forward secrecy: a stolen device key exposes old messages sealed to it.
Found a problem? Email security@beckoncli.com. See also the FAQ.