Security posture

Last updated

Account security

  • You can sign in with an email address and password, or with Google or Apple. An account has no password at all when you only ever use a provider — there is nothing to leak in that case.
  • Passwords, where you set one, are hashed (bcrypt); we never store them in plaintext.
  • Sign-in is timing-safe and returns generic errors (no account enumeration).
  • From Google or Apple we receive an identifier, your email address and — once, if you allow it — your name. We do not ask for, receive or keep any other data from your account there, and we store no access or refresh token for it.
  • A social identity is joined to an existing account of yours only when the provider confirms it has verified that email address. If it has not, we refuse rather than link — otherwise anyone able to set an address at a careless provider could reach your account.
  • Apple's Hide My Email relay addresses work normally; we treat them like any other address.
  • We email a link to confirm your address. It is single-use, expires, and only its hash is stored — a copy of our database contains no usable links. An invalid, expired and already-used link are answered identically, so a stranger holding one learns nothing from us.
  • You can turn on two-step sign-in on your account page: signing in then also asks for a 6-digit code from an authenticator app on your phone — after a password and after Google or Apple alike, and for the desktop and phone apps too, which sign in through this site. The setup QR code is drawn in your browser, never by another service; the key behind it is stored encrypted, and each code is accepted only once. You get ten backup codes, each usable once and stored only as a hash. Repeated wrong codes pause sign-in for a while. Turning it off needs your password (or a recent sign-in) and a code, and signs you out everywhere else.
  • You can add passkeys on your account page and sign in with your fingerprint, face, device PIN or a security key instead of a password. The private key never leaves your device or password manager: we store only its public key, the name you give it and when it was last used. Each sign-in answers a one-time challenge that expires after five minutes and is stored only as a hash, and it only works on this site. Your device checks it is you every time, so a passkey signs you in on its own — no code from your authenticator app. Adding or removing one needs your password (or a recent sign-in).
  • Sessions are signed and can be ended remotely: changing your password, or choosing Sign out everywhere on your account page, signs out every other browser within five minutes, and signs out the apps as well. You can delete your account and data at any time.

Tokens

  • Workspace invite tokens and server-link tokens are stored only as SHA-256 hashes; the raw value is shown once.
  • The entitlement API authenticates a linked server by its hashed token; a database leak exposes no usable tokens.

Billing

  • Card data never touches our servers — the payment provider handles it.
  • Subscription state is written only by webhooks whose signature we verified, each deduplicated by event id; a client cannot assert a plan.
  • That deduplication ledger keeps the event reference, its kind and its timestamps — and never the provider's message body, which carries the customer's name, billing address and card country. Rows are deleted after 180 days.
  • Paddle is the merchant of record for new subscriptions — it is the seller, issues the invoice, and collects any VAT due.

Third parties

  • Paddle — sells and bills web subscriptions as merchant of record; an in-app subscription is billed by the store you bought it from.
  • Google or Apple — only if you choose to sign in with them.
  • Google Firebase Cloud Messaging — delivers push notifications to your phone, only if you enable them.
  • Google Firebase Crashlytics — receives the phone app's native crash reports, unless you switch them off.

Connections through our relay

End-to-End Encrypted. Remote sessions are encrypted between your paired devices and your computer, so our relay cannot read them. The relay still sees when you connect and how much data moves. Web previews are not end-to-end encrypted, and notifications go through a separate service that sees the session, the event type and your computer's name, never what is in the session. On your own network, the relay is not involved.

This is how your phone reaches your computer through your Agent Remote account when it is away from your network. Your phone and your computer agree on keys directly — your computer's key comes from the pairing QR code you scanned, never from the relay — so the relay forwards only encrypted data, and it cannot change, replay, reorder or inject a message without the connection breaking.

What the relay still sees is what it needs to route the connection:

  • your computer's relay hostname and the account link it belongs to
  • your phone's IP address
  • that an encrypted connection exists, and when it opens and closes
  • how many messages pass, their timing, and their size, rounded up by padding so exact keystroke and command lengths stay hidden
  • whether your computer is online

Our administrators can see which linked computers are connected to the relay right now, when each one connected, and how many connections are open through it, never what passes through them.

These are not end-to-end encrypted:

  • Web previews. A preview of your dev server opened on your phone passes through the relay, which sees those pages, and the preview's access token and cookie, in the clear while they pass.
  • Notifications. The push signal is a separate channel through this service, limited to the fields listed under Your machine below. It never carries terminal content.
  • Your own network. Your phone reaches your computer in one of two ways: through our relay, as above, or on your own network, where it connects straight to your computer. That local connection is not encrypted unless you turn on TLS on your computer.
  • A computer set to allow unencrypted connections. Your computer refuses unencrypted relay connections by default. If you set relayPlaintext to allow, the relay can read the session while it passes through.

Your machine

The Agent Remote software runs on your own hardware. This cloud service manages your account, workspace and plan, carries the encrypted relay connection described above, and — only if you enable push notifications — relays a minimal attention signal to your phone: a session id, the event kind, the shape of the question (yes/no or a menu — never its text), a label you chose for the computer, that computer's random identifier (so your phone answers the right one), and your device token. That signal never carries your terminal content; the relay accepts those six fields and drops anything else rather than forwarding it, so that stays true regardless of what a future client tries to send. The software on your computer keeps working even if this service is unreachable.

When it checks your plan, each linked computer also sends its name, operating system and version, and processor type. We use them only to show your computers in your workspace's list, so you can tell which is which.

Crash reports and update checks

A crash report and the desktop app's update check leave your machine on their own, and both are narrow. On a machine whose settings an administrator applied there is a third, covered below. The desktop app sends a crash report after a crash — the error, the version, the platform, and a diagnostic line with credentials stripped out locally before sending; if that stripping cannot be completed the report is discarded rather than sent. A report carries no code, terminal output, screen contents or files, and is not linked to your account, your workspace or your email. It is not completely untraceable, though: we keep a scrambled fingerprint of the network address it arrived from, so one machine cannot flood us with reports — never the address itself. You can switch this off in Config, and the app says so on first run. Crash reports are deleted after 90 days.

The phone app sends a native crash report to Google Firebase Crashlytics — the stack trace, the app version, the device model and operating-system version, and a random Crashlytics installation identifier. No account, email, workspace or computer name is attached, and it carries no terminal content. You can switch it off in the phone app's Settings ("Send crash reports"), effective from the next app start. Google keeps these for 90 days.

A fingerprint is a pseudonym rather than anonymity. We cannot turn one back into an address, and each store keeps its own separate kind — one address produces a different fingerprint for a crash report than for a support case, so these records cannot be matched up to each other. Within one store the same address repeats, which is what makes a flood limit possible.

The desktop app also checks for updates once at startup against a server we run, sending the version and platform it is asking about. The server package checks only when you ask it to — when you run its update or status command — and never by itself. Updates are never gated on payment: a lapsed account still receives security fixes. Update payloads are verified against a signing key held in the software before anything is written to disk.

Usage counts

We keep daily totals — linked computers that checked in, new and total links, update checks, phones notified, a per-country tally and a per-version/platform/processor tally — and nothing else. They are computed from requests the software already makes, so no new data is collected from your machine to produce them, and the stored unit is a date and a number: no row describes an installation, a device or an account. For the country tally the address is resolved at request time and never written down. That applies to these tallies: the crash reports, support cases and administrator-settings reports each keep a scrambled fingerprint of the address they arrived from, and each section below says so.

Separately, a computer linked to your account can send one report a day of counts only: how often a web preview, feedback and the terminal were used and how often a request was answered from a notification, how often the relay connection reconnected, and how long answering a notification and reconnecting took, as counts per rough time range. No content, commands, file names, computer name or address. We keep one total per workspace per day, delete it after 395 days, and drop any other field. It is on by default, and you can turn it off at any time on your computer; then nothing more is sent.

Support cases and feedback

A support case or a piece of feedback sent from the app is the one thing here that you type and send deliberately — there is no automatic version of it and so nothing to switch off. A case carries your message, the app version and platform, and optionally the same diagnostics a crash report would, through the same redaction; never terminal output, session content, code or files.

Feedback carries less: the message and the email address you chose to give. No diagnostics are offered or attached, because an opinion is not a fault report.

It is also not anonymous, and only as far as you make it. The case is identified by a one-time code the app keeps so it can show you the status — we store only a hash of it, never the code. An email address is optional and typed per case; without one the case is filed and readable by you, with nowhere for us to reply. Signing in is never required. As with a crash report, we keep a scrambled fingerprint of the network address the case arrived from — never the address itself. Cases are deleted after 30 days without activity, sooner than crash reports, because a case can carry an email address you typed, which a crash report never does.

You can also write to us from the Support page on this website. That message is kept the same way, with two differences: an email address is required, because the website has no other way to reply, and nothing from your computer — no app version, platform or diagnostics — is attached. A web support message stores your message, the reply email you give, and a salted address fingerprint (a scrambled fingerprint of the network address it was sent from — never the address itself). If you are signed in, it is also linked to your account. Messages that look automated, and too many from one address, are refused and not stored; the note we keep of a refusal holds only that salted fingerprint and is deleted after 180 days. A message we did store follows the same 30-day deletion.

You can also email the support address, [email protected]. That email becomes a support conversation kept the same way: we store its text — never its formatting or pictures, and not its attachments, only each attachment's name and size — the address it came from, and our replies, so the conversation stays in one place. Emails that fail the check proving who sent them, and too many from one address, are refused and not stored; the note we keep of a refusal holds only a salted fingerprint of the address and is deleted after 180 days. A conversation is deleted 30 days after its last message.

Settings applied by an administrator

This applies only if someone administers this software for you — a workplace, or a team you belong to. If you installed it yourself you are your own administrator, there are no applied settings to check, and nothing here ever happens on your computer.

Where an administrator has applied settings, your computer checks they are genuinely theirs before using them. If it cannot read them, or cannot confirm they are the ones your administrator applied, it stops rather than run with settings nobody chose — and it tells us, so your administrator can be told. The settings that work this way are the ones that decide what a device may reach and what is recorded; the rest stay yours whoever administers the software.

If those settings have simply expired rather than been altered, none of that happens: your computer goes back to using its own settings, carries on, and sends nothing.

That report is sent automatically and you cannot turn it off. It is the only thing on this page with no switch. Turning it off is exactly what someone bypassing their administrator's settings would do, so the report is not a by-product of the check — it is the check. The app tells you on screen that it was sent.

The report says which of the two failures it was, and carries a reference for the settings being checked so your administrator can match it to what they applied. It identifies the computer and the workspace it belongs to, and carries the app version, your operating system and processor architecture. We also keep a scrambled fingerprint of the network address it arrived from — never the address itself — only to stop one computer flooding us with reports.

It is not anonymous. Along with a support case, it is one of the two things here that names you — and unlike a support case, you did not choose to send it. It carries no terminal output, session content, code or files. If your computer cannot reach us it keeps the report and sends it the next time it can: disconnecting delays it, it does not prevent it. These reports are deleted after 30 days, sooner than crash reports, for the same reason support cases are.

Reporting

To report a security problem, email [email protected]. Please include what you found and the steps to reproduce it, and give us a chance to fix it before you share it publicly. This address is for security reports only — for help with the app, use the support address above.