Skip to content

Pinning detection

Some apps refuse to trust user-installed CAs no matter what. Even with Probe’s CA installed and trusted on the device, the TLS handshake fails and the connection drops — usually with no error visible to you, just a feature in the app that quietly stops working. That’s certificate pinning, and Probe surfaces it with a banner the moment the pattern shows up in traffic.

This page explains what pinning is, how Probe detects it, what the banner shows you, and what you can do about it.

When Probe intercepts an HTTPS connection, it mints a leaf certificate signed by Probe’s local CA. Devices that trust the Probe CA accept that leaf and the handshake completes — Probe sees plaintext on both sides. See HTTPS Interception for the full handshake walkthrough.

A pinned client doesn’t ask the OS trust store. It ships its own list of acceptable certificates (or public-key fingerprints) and rejects anything outside that list, including Probe’s leaf. The handshake dies before any HTTP request flows. Common offenders:

  • Apple identity services (passkey sign-in, iCloud authentication)
  • Google sign-in flows
  • Banking, fintech, and payment apps
  • Messaging apps that emphasise privacy (Signal, some WhatsApp endpoints)
  • Anti-fraud and analytics SDKs embedded inside otherwise-debuggable apps

There’s no proxy-side fix. Pinning is enforced inside the app binary — the only knob is on the app side.

Probe instruments two per-host counters in the proxy hot path:

  • attempts — incremented when the client opens a CONNECT host:port for MITM.
  • successes — incremented when an inner HTTP request actually flows through that MITM tunnel.

A host is flagged as suspected pinning when, inside a sliding 30-second window, it has accumulated 3 or more attempts with zero successes. In other words: three or more times the client opened a tunnel, and not one of those tunnels carried real traffic — every handshake collapsed.

Once a host fires, Probe silences further flags for it for one hour. Without the silence, a noisy app retrying every few seconds would spam the banner forever; with it, you get one notice, take action (or dismiss), and move on.

A background task runs every 5 seconds, drains any newly-flagged hosts from the detector, and pushes them to the UI. As soon as a host produces one successful inner request, its counters reset and Probe stops suspecting it — so a brief network blip won’t trigger a false positive.

When the detector flags one or more hosts, a yellow strip appears at the bottom of the main window — below the status bar on macOS, pinned to the bottom of the layout on Windows. It does not push the log table or status bar around when it appears.

The headline names the most-recently-flagged host:

Probe couldn’t intercept TLS for accounts.example.com

Likely certificate pinning. Login or passkey flows may fail until this domain is added to the ignored list.

Three buttons sit on the right:

  • Add to Ignored — adds the host to your Ignored list. From that point on, Probe stops trying to MITM that host and silently forwards its CONNECT tunnels through. The pinned client gets the real origin’s certificate, so its handshake completes and the feature works again — at the cost that you can’t inspect that traffic.
  • Dismiss — removes the banner without changing anything. The host is silenced for the rest of the session; restarting Probe brings it back if the client keeps failing.
  • Show All (N) — appears only when more than one host is currently flagged. Opens the Suspected Pinning child window.

A standalone window listing every flagged host as a row. Each row has its own Dismiss and Add to Ignored buttons that do the same thing as their banner counterparts but for that specific host.

The list shrinks as you act on rows. When the last host is gone, an empty-state message takes over: No suspected pinning hosts. You can leave the window open as more flags arrive — they’ll appear in real time, since the list is mirrored from the main window.

The only way to open the window is the Show All button on the banner. There’s no menu entry — if no hosts are currently flagged, there’s nothing to show.

Pinning is enforced by the app, not by the network. The workarounds:

  • Use a debug build of your own app that opens up Network Security Config (Android) or relaxes ATS pinning (iOS). For Android, that’s the same Network Security Config snippet covered in Mobile Setup. Drop pinning entirely in debug builds — the production build keeps it.
  • Skip the pinned host. If the failing host is an SDK you don’t care about (analytics, crash reporting, an OS identity service), add it to Ignored and let it pass through. You lose visibility on that host but unblock the rest of the app.
  • Test with a different client. If you’re debugging an API endpoint and a particular client pins, try the same request from Composer or curl — neither of those pin, so you can still exercise the endpoint end-to-end.
  • Patch the binary. Out of scope for these docs and out of scope for Probe itself. Frida and similar tools can disable pinning at runtime on a rooted/jailbroken device, but that’s a separate workflow.

What you should not expect: any combination of certificate-trust toggles, Probe settings, or proxy options that “fixes” pinning. There isn’t one. The decision to pin lives inside the app, and Probe sits outside it.

The detector is heuristic, not certain. A host that’s down for 30 seconds while a client retries the connection three times will look identical to a pinned host from Probe’s vantage point — three handshakes attempted, zero requests flowed. If you dismiss the banner and the host starts working again on its own, that’s almost always what happened.

If you see the banner repeatedly for the same host across sessions, and the app feature tied to that host is broken, pinning is the realistic explanation. If you only see it once and the app works fine afterwards, ignore it.

  • Certificate Setup — the install flow Probe needs to MITM at all.
  • Mobile Setup — connecting a phone, plus Network Security Config for Android.
  • Troubleshooting — broader list of “Probe sees CONNECT but no body” issues.