Security
Traffic between your machines is encrypted end to end, so our servers cannot read it. Public links are the one exception, and this page says where.
Who can read what
| What | Who can read it | How |
|---|---|---|
| Terminals, remote commands, SSH | The two machines | End-to-end encrypted. A relay, when used, forwards ciphertext. |
| File transfers | The two machines | End-to-end encrypted. Nothing is stored on our servers. |
| Private access to ports | The two machines | End-to-end encrypted, including the trusted HTTPS names. |
| Terminals in the web console | Your browser and the machine | The encryption runs in the browser. Our servers carry ciphertext. |
| Request inspector captures | Your machine, and your browser while you look | Captures stay on the machine. Our servers never hold them. |
| ENV values | Your devices and the machines you send them to | Encrypted on your device. Our servers store ciphertext only. |
| Public previews and tunnels | The visitor, our edge, your machine | HTTPS ends at the edge, which reads each request to route it, then forwards it to your machine encrypted. Not end-to-end. |
| Config sync files | Whoever can read your Git repository | Plain files in your repository. Paperboat adds no encryption there. |
How traffic travels
Our control plane introduces two machines and checks that the connection is allowed. The traffic itself goes directly between them when their networks permit, and through a relay when they do not.
Direct
Two machines that can reach each other talk peer to peer. This is the usual case, and it never counts against your plan.
Relayed
When a network blocks the direct path, a relay passes the same encrypted bytes along. It has no key to read them.
Public link
A preview or tunnel is for people without Paperboat. Their HTTPS ends at the edge, which forwards the request to your machine.
- Encrypted between your machines. Nothing in the middle can read it.
- HTTPS. Encrypted to the edge, which reads the request to route it.
Direct: machine to machine, end-to-end encrypted. Relayed: through a relay that forwards ciphertext. Public link: browser to edge over HTTPS, then edge to machine, encrypted.
A connection never falls back to something weaker. If the preferred path is unavailable, pb may choose another path with the same encryption. If authentication, a certificate or an access check fails, the connection ends; it does not try a different route.
You can run the relay and the edge yourself. See self-hosting.
What our servers see
To authorize, route and bill, the control plane needs metadata. It does not need content, and it is not given any.
They hold
- Your account email and how you signed in
- Machine names, operating system, version and online state
- Public keys and certificates of your machines
- Network addresses while two machines are being introduced
- Which machine connected to which, when, and by which path
- How many bytes went through relays and edges, for billing
- Audit events: who did what to which machine, allowed or denied
- Names of ENV variables, and who may receive them
They never receive
- Terminal input and output
- Commands you run and their arguments
- File names, paths and contents
- SSH traffic
- Traffic to private ports
- ENV values, your master password and recovery code
- Any machine's private key
- Requests captured by the inspector
A relay or an observer on the network can still see that two addresses are talking, when, and roughly how much. Encryption does not hide that.
Keys and identity
Each machine creates its own identity keys when it is set up. The private keys stay on that machine, in the operating system's credential store where there is one, or in files only your user can read on a headless server. They are never sent to us and never appear in logs or diagnostic bundles.
Our server registers the public half and issues short-lived certificates that tie a key to your account and that machine. Two machines verify each other's certificates before any traffic flows, so a relay or our own control plane cannot stand in the middle of a session and read it.
Signing in uses a hosted identity provider. When you run pb login, your browser shows a short code and asks you to
approve that computer; no token is ever put in a URL. Sessions are short-lived and refreshed, and each refresh replaces the last.
ENV values
ENV values are encrypted on your device before they are uploaded. The keys are unlocked by a master password, with an optional recovery code. Neither is sent to us, so we cannot decrypt your values and cannot reset your password.
A machine that should receive a value has its own key pair, and gets only the selected values encrypted to it. It never receives your personal or team keys. Unlocked keys are kept in the operating system's credential store; on a headless Linux server they live in memory for 15 minutes and are never written to disk.
Rotating keys after you remove a machine stops it from reading anything new. It cannot make that machine forget values it already had, so change those secrets at their source too.
Access and revocation
Every action on a machine is checked against the workspace's policy before it is allowed, by the server and again by the machine that is being reached. Joining a team grants nothing by itself.
Removing a person, a rule or a machine ends the sessions that depended on it within seconds, including open SSH connections. API tokens expire, can be narrowed to single actions, and lose access when their creator does.
If our servers are unreachable, machines that already trust each other keep working with the access they last verified. A revocation that was delivered before the outage stays in force. This is a deliberate trade: an outage on our side should not lock you out of your own machines.
The audit log records who did what, to which machine, and whether it was allowed. It never contains terminal or file contents.
Updates
pb updates itself from signed release metadata. It checks the signature, the file's hash and that the version is not
older than the one installed before anything is replaced. A new version whose background service fails to start is rolled back.
Updates install at 04:00 local time by default. pb update settings changes the time or turns automatic updates off;
pb update check and pb update download let you review a release first.
What we cannot protect
- A compromised machine. Traffic is decrypted on your machines. Whoever controls one can read what reaches it and use the keys on it. Remove the machine and rotate what it knew.
- Public links. A preview or tunnel without
--privateis on the internet. Anyone with the address can send it requests, and our edge handles those requests in the clear. - People you let in. An interactive participant in a shared terminal types with your shell's permissions. A new participant sees recent output.
- Metadata. Timing, sizes and network addresses are visible to relays and to us.
Audits and source
Paperboat has not had a third-party security audit and holds no certification such as SOC 2. When that changes, the report will be linked here.
The source code of the client, the relay, the tunnel edge and the server is public at
github.com/pinksaucepasta/paperboat as open source (MIT and AGPL-3.0). The
claims on this page can be checked against it; the threat model is in cli/docs/threat-model.md.
Reporting a vulnerability
Please report privately, not in a public issue. Until a dedicated security address is published on this page, use the contact in the repository's SECURITY.md. Include what you found and how to reproduce it; a person reads every report.
Start with the machine in front of you
Install Paperboat here, then on a second machine. Free for personal use, no card needed.
$ curl -fsSL https://get.pprbt.dev/install | bash > irm https://get.pprbt.dev/install.ps1 | iex