Tapproval

Security: what Tapproval can see, and what was fixed

Tapproval answers permission prompts, so a bug in it is a bug in somebody's permission boundary. This page says what it can see, what it promises, what it does not protect against, and every security fix so far. The computer half is open source, so each claim here can be checked in the code.

What Tapproval can see, and where it goes

A small helper on your computer, Tapproval Base, sees what Claude Code asks permission for: the command, or the file and what would be written to it. For the session list it also reads Claude Code's transcripts on that computer. It sends a short card to your watch and prints your answer back to Claude Code. There is no server of ours, no account and no telemetry. Cards take one of three routes:

The privacy policy has the same routes, with what each part stores.

The rules it will not trade away

What it does not protect against

Fixes, disclosed

Newest first. Each entry says what was wrong, when, who could have used it, and the fix. Starting Claude Code once updates the helper.

1.1.45, 12 October 2026: a test copy of the app could answer real prompts

What was wrong. A copy of the watch app running in Apple's Simulator on a Mac, the way the app is tested, could be paired like a real watch and then answer the prompts waiting on that computer. A tap meant for a test card once allowed a real one when the list moved under it.

Since when. From the first public release until 1.1.45.

Who could have used it. Nobody from outside. It needs a paired copy of the app on your own Mac, so the risk was a mistaken tap during testing, not an attack.

The fix. A Simulator copy marks every request, and the helper refuses its answers, its messages to a session and its new sessions unless it was started for testing. Over iCloud, a Simulator copy writes no answers at all. A real watch never sends the mark and is trusted by its key, as before.

1.1.38, 5 October 2026: a program on the computer could pair by using its Wi-Fi address

What was wrong. The relay refuses to give a watch key to a program on the computer itself, because such a key would let a command Claude runs answer its own prompt. It recognised such a program only by the address 127.0.0.1. A program that asked through the computer's own Wi-Fi address instead looked like a watch. --pair, which opens the door without asking, could be run by any program too. So a command running on the computer could open the door and take a key, then answer its own CRITICAL prompt. Separately, any program on the computer, including one run by another user account, could unpair the watch or replace its key.

Since when. From the first public release until 1.1.38.

Who could have used it. Only something already running on your computer, such as a command Claude was talked into running by a web page or file it read. Nobody on the network could use it.

The fix. A program on the computer is now recognised whichever of the computer's addresses it uses, and it is never given a key. Unpairing, replacing the key and the other administration need the key file too, which only your own user account can read. --pair reads that file and signs with it, so the key itself never travels. Without the file, opening pairing still works, but the computer asks "Allow a watch to pair?" first. A new session started from the watch can no longer begin with ! (a shell command) or # (a memory note). Tests show each of these fails without its fix.

1.1.36, 3 October 2026: a computer that had never paired offered a key to its Wi-Fi

What was wrong. So that a first watch could pair with no typing, a computer with no watch paired yet opened its network pairing door by itself for half an hour, again at every Claude Code session start. Anyone on the same network who asked during that time was given a key, and with it could read sessions and answer prompts, CRITICAL ones included. Until 25 September that key was the computer's main key; from then on it was a device key that could be seen and revoked, but still a key.

Since when. From the first public release until 1.1.36. Since 25 September, never on a Mac with the iCloud bridge, which pairs through your Apple ID instead. Never through the travel address.

Who could have used it. Someone on the same local network, such as a café or office Wi-Fi, as a computer that had the helper installed and no watch paired yet. Once a watch had paired, the door stayed shut unless you opened it.

The fix. When a watch asks, the computer now shows "Allow a watch to pair?" with the asking address, and gives a key only after you click Allow. Don't Allow, or no answer within two minutes, shuts the door, and only one question is shown at a time, so a stranger cannot keep putting it on your screen. --pair, which you run yourself, asks nothing more. Tests check that a refusal gives no key and that a late answer cannot shut a door you opened since. Release notes.

1.1.27, 27 September 2026: a request could borrow the key of the one before it

What was wrong. Several requests can share one network connection. The helper kept what it had learned about a request, including whether its key had been proved, on the connection instead of on the request. A request without a key, sent on a connection just after a request that did prove a key, was treated as proved.

Since when. From 1.1.21 (25 September 2026), when signed requests arrived, until 1.1.27.

Who could have used it. Only someone who knew your secret travel address. Cloudflare's tunnel shares connections between callers, so such a person's request could land on a connection your watch had just used, and read sessions or answer a prompt. Without the travel connection turned on, there was no way in.

The fix. Every request now starts from nothing and proves its own key. A test sends a keyless request after a signed one on the same connection and expects a refusal. Release notes.

1.1.21, 25 September 2026: the key stopped crossing the network

What was wrong. Before this, a watch proved itself by sending its key with each request, and it trusted any helper that answered on the right address.

Who could have used it. Someone able to read the traffic, or to answer in the helper's place on your network, could have learned the key.

The fix. Requests are signed and good once, and the helper proves itself in every answer. A Mac with the iCloud bridge never offers a key on the network. The network pairing door hands out a revocable device key rather than the main one. Watches from before signing (the App Store's 1.3 and earlier) still send the key, so the helper still accepts it from them. Every App Store version since 1.4 (2 October 2026) signs; accepting a sent key ends once watches on 1.3 have had time to update. Release notes.

Before the first public release, August–September 2026

Checking a download

From 1.1.27 on, each release carries an archive of its source and a signed statement from GitHub that the release workflow built that archive from the tagged commit. gh attestation verify tapproval-helper-v1.1.27.tar.gz -R marcobelini/tapproval-helper checks it. It proves where a release came from, not that the code in it is safe; for that, the code is there to read.

Reporting a problem

Open a private security advisory, or write to tapproval@thoughtfulsteward.org. You will hear back within a few days. There is no bounty, only credit if you want it, and a fix. What counts, and what is accepted, is in SECURITY.md.

Every release, in order