1. The short answer
The box above is the short answer. If you read one more section, make it section 6: it is the one about what can still go wrong.
2. How a pairing works
The code is cut in two
Eight characters, from an alphabet of 32: the digits 2 to 9 and the letters A to Z, with 0, O, 1 and I left out so nothing is ambiguous when you copy it off a screen.
The first three characters are public. They name a meeting room on our server, which is how your devices find each other. The last five are the password, and they never reach our server in any form, so the relay cannot learn them even in principle. The room name is not made from the password, so nobody who learns it can take it away and grind through guesses offline.
Five characters from 32 symbols is 33,554,432 combinations.
The handshake
Pairing uses SPAKE2, a published standard (RFC 9382), not a scheme we invented. Neither app hand-rolls the maths. The curve arithmetic in each comes from an established library pinned to an exact version (the phone adds one check of its own, that a point it receives lies on the curve, because its library does not make that check), the phone's hashing comes from established libraries held to one version by the app's lock file, and section 7 names the ones pairing uses, including the one place the phone's library falls short of the standard.
Both devices end up with the same key only if both knew the code. There is no partial credit and no "warmer" signal to narrow a search with. A guess either completes or it does not.
Guessing is throttled, twice
- Five wrong tries from one address freeze that address for 30 seconds.
- Ten wrong tries from anywhere at all pause everybody, and one more try becomes possible every 90 seconds after that.
The second limit exists because a single home internet subscriber is routinely handed billions of addresses, so a per-address limit alone is a speed bump. At the fastest rate those limits allow, working through half of the 33.5 million possibilities takes about fifty years. That is arithmetic from the two numbers above, not an attack anyone has run.
A wrong guess does not burn the code
Typing it wrong does not force a new one, so a stranger making one bad guess cannot strand you halfway through your own pairing. The code expires on its own after ten minutes with no pairing activity, and it is replaced after a successful pairing and when the app restarts. Your phone's typing is invisible to the PC, so the code can change while you are typing it. If it does, the PC shows the new one and the old one simply stops working. Nothing is lost: type the new one.
Nothing leaves the PC before the phone has proved itself
An unverified phone is negotiated with on a separate connection built with no screen attached to it at all. The real screen is plugged in only once the PC has verified the phone's proof, so there is no window in which a frame could escape to someone who guessed wrong.
On Windows, the Tether window that shows the pairing code is hidden from screen recording and screenshots by the operating system, always, with no setting to get wrong. On a Mac, Tether asks macOS to hide it the same way, but recent versions of macOS no longer honour that request for every recording tool, so on a Mac do not count on it.
The phone is deliberately not the same. Android can blank the app the same way and Tether offers it as a switch, "Block screenshots & recording", but it ships off because many people reasonably want to record or cast their own session. With it off, anything recording your phone's screen can see the code while you type it. The switch is in Settings and covers the whole app.
The same goes for Tether on another computer when you type a code into it to view this PC. That window is deliberately not hidden from recording, because blanking it would also blank the screen you connected to, and there is no switch for it.
What the phone keeps afterwards
A key that was never transmitted: both devices worked it out independently from the handshake. It moves forward on every reconnection.
Moving forward does not shut out a stolen copy. Each new key is worked out from the one before it, and the formula is published, so whoever holds a copy can move it forward too and keep connecting. The PC accepts the key it holds, the one before it and the one after it. That grace exists because without it, one lost confirmation message would lock you out of your own PC. What gives a copy away is your own phone: once a copy has been used, your phone's next reconnection arrives out of step, and the PC records it as a possible copy. That alone cuts nobody off, but if whoever holds the copy reconnects with it twice or more before your phone does, carrying it forward each time, your own phone is no longer accepted while the copy still is. To shut a copy out, forget the phone on the PC and pair it again.
The phone also pins the PC's certificate. On your home network it will not connect to a PC showing a different one. If it can still reach your PC over the internet it connects that way instead, where the PC must still prove it holds your pairing key. If it cannot, it stops and says "This PC doesn't look like the one you paired with…". The only ways back are deliberate: scan the PC's QR code again, or forget the PC and start over.
That pin is only accepted from a route that is already trustworthy: through the QR code, which travels from the PC's screen to the phone's camera and never touches the network, inside the handshake under a tag only a device holding the handshake secret could produce, or from the PC itself inside a session that has already proved it holds your pairing key, and then only when the phone holds no pin yet. A tampered tag aborts the pairing, and a pin learned from the QR code is never overwritten.
3. What protects a live session
Everything rides on one standard WebRTC connection encrypted with DTLS-SRTP, the same mechanism that protects browser video calls. It carries the screen, the PC's sound, and three data channels: control and file transfer, both of which never drop anything, and cursor movement, which is allowed to drop packets because a mouse position that arrives late is worse than one that never arrives.
Tether does not choose the encryption algorithm. The two WebRTC implementations negotiate it at runtime and nothing in our code pins one, so we name the mechanism, which you can check in our source, and not an algorithm we cannot guarantee.
Why the relay cannot quietly sit in the middle
"The server just passes messages along" is not a guarantee by itself: a server that passes messages along could substitute its own instead.
So both devices fold the connection's cryptographic fingerprints into the proof they exchange while pairing. Anything that re-terminated the connection in the middle would change a fingerprint, the two sides would compute different keys, the proofs would not match, and pairing aborts. That is a property of the maths, not a promise about our conduct. The same binding protects every later reconnection, each with fresh random values from both sides so a recorded proof cannot be replayed.
One detail, because this is the sort of thing that fails quietly: if a setup message carries more than one fingerprint and they disagree, pairing aborts rather than picking one. Without that check a relay could send a decoy alongside a rewritten real one, every proof would still verify, and it would be holding both halves of the call.
The PC does not listen to the whole network
The PC's listener always covers the machine itself, and reaches your home network only when home-network access is switched on, when a phone is already paired, and while the pairing card is open on screen. It never listens on everything. Any connection arriving with a web-page origin attached is refused outright, which closes the trick where a malicious website talks to software on your own machine.
4. What our servers can and cannot see
One server of ours, the switchboard. Its job is to let your devices find each other and swap the messages that start a direct connection, and, on app versions that offer it, to carry your phone's request to one of your PCs to wake another.
What it cannot see
- Your screen, the PC's sound, your keystrokes, your clicks, your files. None of it passes through the switchboard, and it holds no key that could decrypt it.
- The secret half of your pairing code. Only the three public characters reach the server, and the room name made from them gives no way to test guesses at the password.
- Your PC's real name. Windows and Mac computer names often contain the owner's name, so it is never sent. Your phone sees the word "PC", or the name you gave it in Tether's settings if you chose one. When a connection is set up through our server, our server sees that same word or name too, because it travels in the setup messages we pass along. Your screen's size is not sent either, for the same reason, because an unusual one is a fingerprint; only its shape is, as the ratio of its width to its height.
What it does see
- Both devices' IP addresses, because it cannot answer a request without one. On the metered paths it holds them only briefly in memory to limit how often one address can ask, and the relay's record of a device uses a one-way fingerprint instead.
- Which room, and when. That two devices met, at what time, for how long, and whether one is online now.
- The setup messages, in readable form. They are relayed byte for byte, with no parsing or inspection anywhere on that path, but the server could read them. They hold the handshake values (including a count of how many times this pairing has reconnected), the network addresses your devices offer each other, the certificate fingerprints, the shape of the PC's screen, the PC's display name if you set one, and from your phone a random identifier it keeps for each install, so the PC can find its key, and the app's version number. When your PC lends its relay to your phone, one more message goes this way: the relay's address and a password for it that lasts at most two hours, sealed with a key only your two devices hold, so we cannot open it. The PC's first reply to your phone also carries a plain flag, which we could read, saying whether it has a relay to lend right now. Never any media.
- Your licence code, when your apps send it. They send it to claim a room, to check your access and to ask for relay servers, and it arrives readable. In our logs and on the relay and metering paths it is kept only as a one-way fingerprint under a secret only the server holds. The record that grants your access is separate, and it is filed under the code itself (see section 5).
- A request to wake a PC through another of your PCs, on app versions that offer it. It passes through readable: your phone's identifier, the hardware address of the sleeping PC's network card, the broadcast addresses of the networks it is on, how many times your pairing key has moved forward, a code your other PC gave your phone for that network, and the one word that comes back saying whether the wake signal went out. The proof that the request really comes from your phone is not something we can forge or replay. On these versions, whenever your phone and one of your PCs meet at the switchboard, for a wake, a session or pairing, the switchboard also tells the PC in that room, and nobody else, one word: whether your phone reached us from the same network, from another one, or that it could not tell. It works that out from the same short-lived network fingerprints it already compares to tell whether a session is on your own network, and does not keep the word.
Everything the app sends us, in full
Six requests to us, and this is all of them. The Android app's barcode scanner, which is Google's, also gathered reports for Google in versions before 1.5.22; what we measured about that is in the next subsection.
- The rendezvous connection, whose address carries the room name and whether this device is the PC or the phone, and from the PC the signed room token described next and, on versions that can wake other computers (whether or not that is switched on), a random number made fresh for each connection so the PC can recognise the switchboard's own messages.
- A room claim: the room name and your licence code, which gets back a signed token proving your PC owns that room so a stranger cannot displace it.
- A licence check: the licence code and one word for the device type, "pc" or "phone". No machine identifier, no operating system, no version.
- A request for relay servers, made by your PC when the app starts, as sessions start, and again when a live session's connection breaks and has to be repaired, each time unless it already got an answer in the last minute, and by your phone each time it connects, so a relay is ready if your devices cannot reach each other directly, and only ever to our own switchboard. It carries your licence code, if the app has one. The answer names Cloudflare's servers, and your devices then contact those directly: a public one that tells each device its own internet address, so the two can find a direct route, and the relay itself when one is needed. Both run on Cloudflare, not on machines of ours.
- An update check, identifying itself as the bare word "PCTether". The PC and Android apps make it when they start, the Android app again whenever it comes back to the screen, and the PC also once a day, when it wakes from sleep, and when an update it has downloaded needs a fresh answer before installing (those last two at most once an hour), and whenever you press Check for updates. No version and no machine detail, because a richer string would be a fingerprint we would then be storing about our own users. The PC also makes this same request if a pairing through our server has got nowhere after ten seconds, to tell whether our server or your network is the problem. At that moment it also asks Microsoft's standard connection-test address, the one Windows itself uses.
- The update download itself, only when a newer build exists: the Windows app fetches the installer from our own download address, then checks its size and its published fingerprint before it will install it.
Tether is free while it is in early access. The licence code switches remote access on; nothing is charged for it right now.
No analytics in our apps, and one exception we found ourselves
The PC app and the iPhone app, which is coming soon, contain no analytics, telemetry or crash-reporting product. The Android app contained one until version 1.5.22, and it was not ours. The part that reads the pairing code off your PC's screen is Google's barcode scanner, and in versions before 1.5.22 it gathers reports about that scanner for Google's servers from the moment the camera opens; Google's own terms describe them as usage and performance statistics. We measured this on 24 September 2026 on an Android test device, an emulator: we saw the reports queued and Android's upload job run. We did not capture the traffic or read the reports, so we do not say what is in them. Reading the code itself happens on your phone, and Tether's own code sends nothing to Google.
We removed that reporting part from our code the same morning, and on the same emulator our version then queued no reports at all. That version, 1.5.22, went live on Google Play and as the file on this site on 3 October 2026. Before it went out we checked the shipped file the same way: it read a real pairing code and queued no reports, where the old build queued five. A phone still on an older version keeps the old scanner until it updates.
Our earlier check searched both codebases for every common analytics vendor by name and found none, then ran the same search for a third-party service we do use to prove the search worked. It missed this one because the Google library arrives inside the scanner and is never named in our code.
This website is held to the same rule by its build: if any page's HTML referenced a resource from another company's servers, the site would fail to build and could not be published, and every page also tells your browser not to load anything from anywhere but this site and our own switchboard. The only outside addresses on our pages are ordinary links you can choose to click, and they are of three kinds. The privacy policies of the companies the privacy page names: Cloudflare, Resend, Zoho and Google, and Stripe, which that page lists as not in use today. The published specification for the pairing handshake, linked in section 2 of this page. And the Android app's page on Google Play, which the homepage's download QR code also opens. Web addresses also appear where nothing fetches them: the typeface licence file we are obliged to publish beside the fonts, which prints three of them as plain text you cannot click, and the standard names page code carries, such as schema.org in the summary for search engines and w3.org inside the pictures. Nothing on this site fetches anything from any of them; the typefaces on this page are served from pctether.com for exactly this reason.
5. What is stored, and where
On your PC
- The reconnect key for each paired phone, encrypted with your Windows login (on a Mac, with a key kept in your login Keychain), so a copy taken to another machine or account decrypts to nothing. On versions that can wake other computers, the same sealed record can also hold a second key for that phone, made once you let your phones wake other computers through this PC, and roughly when that phone last asked it to (at most one update a day). If that encryption is ever unavailable the app refuses to save the key at all, and you re-pair on the next launch.
- Your licence code, as plain text in the app's settings file. Anyone who can read your Windows user profile, or your home folder on a Mac, can read it.
- Connection statistics with no addresses in them: what kind of route each connection used, never where the other end was.
- Relay use as monthly totals, for the twelve most recent months in which Tether was used, and sent nowhere.
- An error log with addresses and pairing codes stripped out before anything is written, and your account name stripped from the file paths it records. Windows versions up to 1.5.28 can miss it in two rarer forms: a name with a space in it keeps the part after the space, and a path written with doubled backslashes keeps the whole name.
- A line each time a saved phone login looked wrong, naming which phone and what the PC did about it. No addresses. Versions before mid-August 2026 recorded one, and the app removes those the next time you open it.
- A dated line when each session starts and ends, with why it ended and what kind of route it used. No addresses: the route is a category and the reason is one word from a fixed list. On versions that can wake other computers, it also gets a line for each such request that proves it comes from a paired phone or fails that proof, with one word for what happened (the same outcome again within ten minutes, other than a wake that was sent, is counted on its next line instead), and on a wake that was sent, one more word for whether the switchboard said the phone was on that PC's network or on another one, or gave no answer it could stand behind, and no phone, computer or network named. It rolls itself aside at 64KB so it cannot grow.
On your phone
- The reconnect key, in Android's Keystore, the same place the system offers any app for credentials. On phones with a secure chip it is backed by hardware. We do not check which kind your phone gave us, so we are not going to claim the stronger one. On the iPhone app, which is coming soon, it is in the Keychain, set so that it stays on that phone and is never carried to a new one.
- Your licence code, the PC's address, its name and its certificate fingerprint, in the app's ordinary settings, outside that vault. Readable only to Tether. On Android they are kept out of device backups. On an iPhone they are not: Apple includes an app's ordinary settings in your phone's backups, so your licence code goes with them. Files your PC sends to an iPhone are kept out of those backups.
- Details for waking your PC, on the versions that keep them. After a session on the same network, the Android app that can wake your PC keeps the hardware addresses of up to three of the PC's network cards, the broadcast addresses of the networks they are on, whether each is cabled or Wi-Fi, and what Windows says about it waking the PC, so it can send the wake-up signal later. Newer versions also keep, for each network, a tag made from the hardware address of its router, so the phone can tell two homes that use the same addresses apart. The tag is mixed with a random value the phone keeps beside it, which stops two phones' tags from being compared but does not hide the router from anyone who holds the phone's settings. If the PC lets your phones wake other computers through it, the phone also keeps a code from that PC for each network, which only that PC can check. The iPhone app, which is coming soon, keeps the same details. It cannot send the wake-up signal itself, but newer versions can ask another of your PCs on that network to send it. They sit in the same ordinary settings, so on Android they are kept out of backups and on an iPhone they go with them. Forgetting a PC does not delete them at once: the phone keeps the six most recent and drops older ones.
On our servers
- Your licence code, in readable form on our servers, where it is the name of its own record. Your apps send it to us when they check your access.
- When a code was first used, and the kind of device, so a code being passed around can be noticed. First used means the first time an app checked it, which is not the same as the first time anything connected.
- Setup messages, briefly, and only when one device arrives before the other. Deleted the moment the second connects, or five minutes after the first stops waiting. Everything after that is passed straight through and never written down.
- A line each time a device connects to our switchboard or leaves it, and one when a room clears out what it was holding: the moment, whether it was a PC or a phone, whether a PC proved it was allowed to hold the room, how many earlier connections from the same side it replaced, how many connections the room held at that moment, how many messages the room had received since it was last idle, how long the connection lasted and how it ended. It is filed under the room's own number, which does not contain your code. No code, address, token or device name goes with it, and nothing you saw or typed. Lines with the same number belong to the same room and can be read together. It is there so we can see why a room stayed open long after anyone needed it, which once used up our hosting allowance and stopped everybody connecting from away for six hours. Our hosting provider deletes these lines after three months.
- A short-lived note each time a device with a licence code asks about the relay, which your PC does when the app starts, as sessions start and when a session's connection has to be repaired, each time unless it already got an answer in the last minute, and your phone does each time it connects, not only when the relay is used: the time, and a one-way fingerprint of the address it asked from, which cannot be turned back into an address. It counts how many devices share one licence, and it is deleted about two and a half hours later.
- What our code check answered, with nobody named in it: the moment, one word for the answer, and whether our server replied normally. No code, no address and no device go with it, so the line itself names nobody. It is there so we can tell whether somebody was turned away by a code that did not work, which nothing else we keep can answer. Deleted after ninety days.
- Your email address, if you asked for a code, in two places: the request itself, and the label on the code we send you. Both are deleted the first time your code is used, or within a day of it running out, which for a code nobody ever uses is within ninety days of the day we send it. The cleaner only acts on a code with an end date that has passed, so if yours has no end date, or we have switched it off, ask us and we will remove yours.
- Whether a code went to our own inbox: when we make a code for a waiting-list address we note one answer with it, ours, not ours, or could not tell. It stays on the code's record after your address is deleted, which is how we tell our own test codes apart from real people's. Nothing of your address goes with it. On our own test codes only, we also keep the short tag we typed after a "+" in our own address.
Two copies outlive that deletion. The email that carried your code sits with the service that delivered it, under their retention rather than ours, and our database keeps a restore point for up to thirty days.
Licence codes never appear in logs, on any path.
On this website
Nothing is kept in your browser, with one exception: the thank-you page holds your licence link for that tab only, so a refresh cannot lose a code you have just been given. It goes when the tab closes.
The same ground, as a legal commitment, is in the privacy policy.
6. What this does not protect you from
Anyone who can see the code can pair
A glance over your shoulder, a photo of your monitor, a camera behind you. Any of those is a complete break of first-time pairing. The maths protects the code from everyone on the network and does nothing about a person in the room.
There is no "add a device" mode
While the PC app is running it accepts a brand-new pairing attempt at any moment, and home-network access is on by default once you have paired one phone, so a paired PC keeps a pairing listener open on your Wi-Fi indefinitely. Guessing still takes years, so this is exposure rather than a break, but a stranger on your network gets unlimited throttled attempts and you are never told. There is no switch that closes the door to new pairings alone. The Same-WiFi switch in the PC's window closes the Wi-Fi listener until the app restarts, but it also stops your paired phones using Wi-Fi.
Anyone who controls your PC has already won
Malicious software running as you can read the stored reconnect key and tamper with a live session, because the key is sealed to your account so that you can use it. If your PC is compromised, Tether's encryption is not what stands between you and the attacker.
An unlocked, stolen phone is full control of your PC
The key is in secure storage and the app can sit behind your fingerprint or PIN, but neither helps if someone is handed your phone already unlocked.
And there is no way to unpair it from somewhere else. The only way to remove a phone's access is to go to the PC and forget it there. We cannot do it for you, because there is no account to sign into, and that is the cost of the privacy choice. An unused key expires by itself after 180 days, chosen so a real owner back from a long trip is not locked out, so a stolen phone left switched off is still paired six months later. On a PC that lets your phones wake other computers through it, a phone asking it to do that also counts as use, and it does not show as activity in that PC's list of paired devices. If you cannot get to your PC, keep it turned off until you can.
A PC that wakes other computers for your phones shows nothing while it does
On versions that offer it, a Windows PC has a switch, off until you turn it on: "Let my phones wake other computers on this network through this PC". With it on, any phone paired to that PC can, after proving it holds its pairing key, make the PC send the standard wake-up signal into the network it is on, and nothing appears on that PC's screen when it does. The PC cannot tell whether the computer being woken is yours: it sends the signal to whatever network card the phone names, other than its own. Each phone can make it do that at most once every fifteen seconds and eight times an hour, and the PC does it at most twenty times an hour in all. For a phone on another network, the PC does it only if its code covers connecting from anywhere, the same rule as for a session. That rule rests on the switchboard's word for where the phone is, and when the switchboard cannot tell, for instance because the phone and the PC reached it over different kinds of internet address, or says nothing at all, as a switchboard running older code does, the PC sends the signal anyway. Turn it on only on a PC whose paired phones you would trust with that.
We can see who connected to whom, and when
Both IP addresses, which room, the timing, whether you are online. Not your screen, your keystrokes or your files. But "cannot see your screen" is not "cannot see that you connected", and the second one is not true. Hiding the fact of the connection itself is not something Tether does today.
Your internet provider can see you use Tether
The PC app connects to our switchboard at startup and, once a phone is paired, stays connected for as long as it runs. The PC and Android apps also check for updates when they start, when the PC wakes (at most once an hour) or the Android app comes back to the screen, and while a downloaded update waits to install, and the PC checks once a day as well. The contents are encrypted; the destination and timing are visible to anyone watching your network. No software can change that, and those checks are in effect a regular signal that this device runs Tether.
We do not choose the session's encryption algorithm
DTLS-SRTP is the mechanism and that is verifiable. The specific cipher is negotiated between the two WebRTC implementations at run time and nothing in our code pins one.
The Windows installer is signed, and Windows may still warn you
Since version 1.5.24, released 4 October 2026, the Windows installer is signed by 1000711712 Ontario Inc. That is the legal name of the company behind Tether, and it is the name Windows shows as the publisher when the installer asks for permission to make changes to your device.
Signing does not switch off every warning. Windows also judges a new file by how many people have downloaded it, so while a release is new a box headed "Windows protected your PC" may still appear before the install starts. Before you click through it, you can check the file yourself. Right-click the downloaded file, choose Properties, and open the Digital Signatures tab: it should name 1000711712 Ontario Inc. The fingerprints for every download are published too, with the command to compare them.
The Mac app is signed by the same company and notarised by Apple
The Mac app is signed with an Apple Developer ID in the name of 1000711712 Ontario Inc., and Apple notarises it. The first time you open it, macOS shows a box saying "PC Tether" is an app downloaded from the Internet, and that Apple checked it for malicious software and none was detected. PC Tether cannot record the Mac's screen or control it until you allow each in System Settings, and macOS enforces that, not us. A card in its window shows which is still off and opens the right page.
Signing you in remotely means a Windows service that can reach your login screen
Tether can sign you into a locked PC from your phone, or from another computer running Tether. That only works if something on the PC is allowed to type into the Windows sign-in screen, which is a place a normal program is deliberately locked out of. So the feature runs as a Windows service at the highest level the system has, and while it is on it can see and type into your login screen. That is the whole point of it, and it is also the cost.
It is off until you turn it on. The installer does not set the service up, there is no such service on a fresh install, and you switch it on yourself in Settings with a prompt that asks for administrator permission. If you installed the version that needs no administrator, this part is not on your computer at all: those bytes are left out of that download rather than switched off, so there is nothing there to turn on and Settings says so. A service running that high is a larger target than the app around it, and anyone who already had administrator control of your PC could lean on it, though by then they have already won. We name it here because, once on, it can watch you log in.
Licence checking is not a security control
The apps check their own code, with a fourteen-day offline grace so a network blip does not lock you out mid-session. A modified copy of the app is not stopped by that layer. It sits on top of the encryption and never touches it.
A stranger can block a first-time pairing over the internet
Meeting rooms are named from only the three public characters, and a determined stranger can cover that whole space, so somebody could occupy the room your PC is waiting in and stop a new pairing completing. Our server pushes back on clients that dial many rooms. A PC with a live licence code cannot be pushed out of its room by anyone who does not hold that same code, but a PC without one can be. Either way it is a nuisance rather than a break: occupying a room never reveals the password, which lives in the other half of the code. Already-paired phones are unaffected.
Certificate pinning does not work the same way on both paths
On your home network the phone checks the PC's certificate directly against a copy it remembers. Over the internet it trusts our switchboard's ordinary web certificate for that connection and establishes the PC's identity separately inside the messages, bound to the fingerprints in section 3. The guarantee holds, by a different mechanism than "pinning everywhere".
One asymmetry we have found and not yet fixed
The phone can play incoming sound from the far end before that end has finished proving who it is. Remote control is held back. Video is held back on a first connection; on a silent reconnect the phone can show the new connection's picture before it has finished checking the far end. The reach is narrow, because a legitimate PC attaches no audio until after it has verified the phone, so it only matters against an already-hostile far end. It is still an inconsistency. We found it in our own audit, and it is listed here before the fix ships.
The phone does not meet one requirement the pairing standard sets
RFC 9382 says the curve arithmetic must take the same time whatever the secret is, so that timing it tells you nothing. The library the phone uses does not guarantee that. The exposure is narrow (precise timing needed, the secret lives for seconds, guessing is throttled) and we accepted it knowingly, but it is a stated "must" we do not meet.
A dormant Google push component ships inside the PC app
The installed app contains a file that would send notifications through Google's push service. Nothing runs it, nothing is connected to it, and nothing goes to Google through it. (The Android app's scanner is a separate matter, covered in section 4.) It is an unfinished feature. A page that tells you which servers the app talks to should also name the ones sitting in the binary switched off.
A disabled analytics tag exists in our source, but not in the page you receive
Our own copy of the homepage keeps a Cloudflare analytics snippet commented out, with a placeholder where a token would go. It has never run, and since early August 2026 every comment is stripped from the files the site serves, so it is not in the page your browser downloads. Check with View Source. We name it anyway, because it is one line away from being switched on at our end.
The comment-stripping was not tidiness. Comments are invisible on the page and fully visible in the source, which is exactly what stops anyone noticing them; ours had collected developer notes and internal document names. So we stopped shipping comments.
Cloudflare is an unavoidable third party
Our switchboard runs on Cloudflare, and everything on this page stops at the edge of our own code. One specific consequence: the room name travels inside the web address of the rendezvous connection, and so does a short-lived room token from your PC, which carries a one-way fingerprint of its licence when it has one (never the code itself) and whether that licence covers connecting from anywhere. Web addresses are the part of a request edge logs typically capture. Nothing in our code writes either down. We do not control what theirs does.
Nothing here protects you from someone at your unlocked machine
Your licence code is readable text on disk, the settings file is ordinary text, the session, connection and error logs are ordinary text, the Phone Alerts rules you typed are ordinary text, and the queue of files waiting to send is a plain list of paths. The reconnect keys resist being copied to another computer, but not somebody sitting at yours.
7. For the technically minded
The primitives, named exactly. Anything not on this list is not something we claim.
- Pairing handshake
- RFC 9382 SPAKE2, ciphersuite P256-SHA256-HKDF-HMAC, protocol
profile string tether-pin-pake-v1. The two ends run
different stacks, and the two curve libraries are pinned to exact versions.
PC: group operations
from @noble/curves 2.2.0, HKDF and HMAC from Node's own
crypto. Phone: group operations from
pointycastle 4.0.0 (secp256r1), HKDF and HMAC from
cryptography_plus. The RFC's M and N seed points are
embedded uncompressed as nothing-up-my-sleeve constants.
One known shortfall, on the phone. RFC 9382 §7 says the scalar multiplication MUST be constant-time; pointycastle's is not. A library that takes a measurably different amount of time depending on the secret can, in theory, leak that secret to something able to measure it precisely. We judged the practical risk small (the secrets exist for seconds and guessing is throttled), but it is a stated MUST that we do not currently meet. Section 6 says so, where a reader can find it. - Password derivation
- The five password characters are turned into a scalar and never sent: w = OS2IP(HKDF-SHA256(ikm = utf8(password), salt = empty, info = "tether-pin-pake-v1|w", L = 40)) mod n Forty bytes of output gives 64 bits of headroom over the curve order, which removes modulo bias. Nothing derived from the five password characters crosses the wire except 65-byte curve points, 32-byte HMACs and, when the PC lends its relay, the sealed message below.
- Code layout
- 8 characters over a 32-symbol base32 alphabet (2-9, A-Z, less 0/O/1/I). Characters 1-3 are public; characters 4-8 are the SPAKE2 password. 325 = 33,554,432, about 25 bits.
- Rendezvous room
- Derived from the PUBLIC slice only, so it is not an offline oracle for the password: roomId = base32(HKDF-SHA256(ikm = utf8(Cpub), salt = empty, info = "tether-room-v1", L = 5)) The result is 8 base32 characters.
- MITM binding
- Both DTLS certificate fingerprints are bound into the
confirmation keys, in a fixed PC-then-phone order:
AAD = utf8(fpPC) ‖ 0x00 ‖ utf8(fpPhone)
KcA ‖ KcB = HKDF-SHA256(ikm = Ka, salt = empty, info = "ConfirmationKeys" ‖ AAD, 32)
cA = HMAC-SHA256(KcA, TT)
cB = HMAC-SHA256(KcB, TT) A relay presenting its own certificate changes a fingerprint, so both MACs fail. - Fingerprint parsing
- Line-anchored extraction of every a=fingerprint line, canonicalised; a value is returned only if the set collapses to exactly one. More than one distinct fingerprint aborts the pairing rather than picking a winner.
- Pairing key
- Derived on both sides and never transmitted in any form: pairingKey = HKDF-SHA256(ikm = Ke, salt = empty, info = "tether-pin-pake-v1|pairing-key", L = 32) Here Ke is the first 16 bytes of SHA-256(transcript).
- Reconnect proof
- Sent on every reconnection in place of the code: HMAC-SHA256(pairingKey, utf8(role) ‖ 0x00 ‖ nonceH ‖ nonceP ‖ 0x00 ‖ utf8(fpPC) ‖ 0x00 ‖ utf8(fpPhone)) The role is one of the anti-reflection literals "phone" or "PC", and both nonces are fixed at 16 bytes. Fresh nonces make a captured proof replay-dead; the fingerprints make it die if the media path was re-terminated.
- Key ratchet
- Applied on every reconnect. The PC accepts a phone's proof under the previous, current or next generation: a two-step grace plus a bounded one-step forward catch-up, so a crash between advancing and saving never strands the owner. The phone checks the PC's proof under its one current key. The next key depends on the previous key alone, so a captured key can be carried forward by whoever holds it; replaying the captured bytes unchanged stops working after two legitimate reconnects, and out-of-step use raises a possible-copy signal: key(n+1) = HKDF-SHA256(ikm = key(n), salt = empty, info = "tether-reconnect-v1|ratchet|" ‖ uint32be(n+1), 32)
- Relay lending
- When the PC lends its relay to the device it has just verified,
it sends the relay's details once, immediately before its own confirmation and only
after that device's proof has verified. They are sealed with AES-256-GCM (a random 12-byte
nonce, a 16-byte tag, the message type and kind as associated data) under a key only
this session's two ends hold:
first pairing: HKDF-SHA256(ikm = Ke, salt = empty, info = "tether relay-share v1|v3", L = 32)
reconnect: HKDF-SHA256(ikm = pairingKey, salt = empty, info = "tether relay-share v1|v4" ‖ nonceH ‖ nonceP, L = 32) A plain flag in the PC's first reply, readable by our server and by anyone dialling, says whether a relay is on offer. - Certificate pin
- Checked as an exact SHA-256 of the
certificate's DER bytes on the direct/LAN leg only. The PC's certificate is self-signed,
so it always reaches that check; a certificate your phone's system already trusts
for that address would be accepted without it.
A mismatch raises a fingerprint-mismatch error and there is no plaintext leg on that
path to fall back to, so a downgrade is structurally impossible rather than forbidden
by policy. The pin is accepted only out-of-band via the QR code's fingerprint field, or
in-band carried by an authentication tag:
fpMac = HMAC-SHA256(master, utf8("tls-fp") ‖ 0x00 ‖ utf8(fpHex))
master = HKDF-SHA256(ikm = Ke, salt = empty, info = "tether-pin-pake-v1|master", 32) - Session transport
- One RTCPeerConnection: a sendonly video transceiver, a sendonly audio transceiver, and three SCTP data channels: control (ordered, reliable), file (ordered, reliable) and input (ordered, maxRetransmits: 0). Data channels ride SCTP inside the same DTLS association as the media. DTLS-SRTP; no cipher suite is pinned anywhere in our source.
- Pre-auth isolation
- An unverified peer negotiates on a second, isolated peer connection with trackless sendonly transceivers. DTLS may complete before the confirmation or, when the phone is waiting for a lent relay, usually only after it (the phone waits at most four seconds). Either way no media exists to leak. replaceTrack() fills the senders only after the host has verified the MAC.
- Throttles
- Per-IP: 5 failures, 30-second cooldown. Global: a bucket of 10 tries refilling one try every 90 seconds, so guessing is held to 960 attempts a day on average, plus a fresh burst of 10 each time the app starts. Both evaluated before any curve arithmetic runs.
- Network perimeter
- Binds 127.0.0.1 always, and concrete LAN IPv4 addresses only when LAN exposure is on. Never 0.0.0.0. Any WebSocket upgrade carrying an Origin header is refused with 403 before a socket exists, which closes browser-driven DNS rebinding.
- At rest, on the PC
- Electron safeStorage, which is Windows DPAPI, or the login Keychain on a Mac, bound to the logged-in account. Fail-closed: if sealing is unavailable the store writes nothing and keeps trust in memory for that session only. The identifiers of the devices paired to it are persisted as SHA-256 only.
- At rest, on the phone
- Android Keystore-backed secure storage for the reconnect credential, the device identifier, this phone's approval signing key and any other saved PCs. The current PC's address, its display name, its certificate pin and the licence code are app-private SharedPreferences, outside the Keystore. The app is built with allowBackup="false", so none of it leaves the device in a backup.
- At rest, on the server
- Wherever the relay meter or a meeting room needs to tell one licence from another, and in every log line, a licence code appears only as a domain-separated keyed HMAC, truncated, under a server secret. The code itself is still the name of its own record in our licence store, as section 5 says. The HMAC was chosen over a plain hash specifically so that an attacker holding a dump of the meter plus a candidate code could not recompute the value and confirm the code was live. Client IPs on the metered path are fingerprinted the same way.
If something on this page is wrong or missing, write to support@pctether.com.
8. Reporting a security problem
Found a weakness in PC Tether? We want to hear about it. A false alarm beats a missed one.
support@pctether.com. A person reads it. Start the subject with Security so it isn't treated as ordinary support.
What helps most
- What you found, and what an attacker could do with it.
- Steps to reproduce it, plus your Windows/Mac/Android and app versions (app version is at the bottom of the PC window).
- A fix, if you have one. Welcome, never required.
What we will do
- Reply within five working days. No answer by then? Resend. It went astray.
- Tell you whether we agree it's a problem, and if not, why.
- Keep you posted, and tell you when it's fixed.
- Credit you in the release notes, or not. Your call.
Please don't
- Test against anyone else's computer, phone, or code. Use your own.
- Flood or denial-of-service the relay. It's small, and all you'd do is take it down for real users.
- Go public before a fix ships or 90 days pass, whichever comes first.
Our side of it
If you follow the two lists above and report in good faith, we will not pursue legal action against you, and we will not ask anyone else to. We treat that kind of research as help. If you are not sure whether something is in bounds, ask first and we will tell you.
One thing up front: there is no bug bounty and no payment. Tether earns nothing today, so there is nothing to pay from. What we can offer is a fast answer from the person who wrote the code, and public credit if you want it.
Machine-readable version of this section: /.well-known/security.txt.