Passkeys were supposed to kill passwords for good.
The pitch was clean: use a cryptographic key pair tied to your device, authenticate with a fingerprint or face scan, and never type P@ssw0rd123! again. Apple, Google, and Microsoft all shipped passkey support. FIDO Alliance called it the "beginning of the end" for passwords. Developers started integrating WebAuthn into their auth flows, and security teams celebrated.
Then Unit 42 at Palo Alto Networks dropped a research paper that complicates that narrative.
Their findings, published under the title "Pass the Passkey," show that passwordless authentication has its own class of vulnerabilities. Actual, reproducible attack paths that can intercept and relay passkey authentication in real time.
If you've implemented passkeys in your app, or you're planning to, this matters.
How Passkeys Actually Work (Quick Refresher)
Before we get into the attack, a quick grounding in how passkeys function under the hood.
When a user registers a passkey with a service (the "relying party" in FIDO2 terminology), their device generates a public-private key pair. The private key stays on the device, protected by the platform authenticator. Touch ID, Windows Hello, whatever your platform uses. The public key gets sent to the server.
During authentication, the server sends a challenge. The authenticator signs that challenge with the private key. The server verifies the signature against the stored public key. No shared secret crosses the wire.
This model is genuinely strong against traditional phishing. You can't clone a passkey by tricking someone into entering it on a fake site, because the private key never leaves the device. Credential stuffing doesn't work. There's no password database to exfiltrate.
But strong against traditional phishing doesn't mean immune to everything.
What Unit 42 Found
The core of the "Pass the Passkey" attack is a relay pattern. Think man-in-the-middle, but applied specifically to the WebAuthn authentication ceremony.
The sequence goes like this:
- The victim visits what they think is a legitimate site. It's actually the attacker's proxy.
- The proxy initiates a real authentication session with the actual target service.
- The target service sends a WebAuthn challenge back through the proxy to the victim's browser.
- The victim's authenticator signs the challenge, believing it's authenticating with the real site.
- The signed response travels back through the proxy to the target service.
- The attacker now has an authenticated session.
The victim sees a normal passkey prompt. They approve it with their biometric. Everything looks fine from their end. But the authentication actually happened on the attacker's session.
The cryptography worked correctly. The signature is valid. The challenge-response protocol did what it was designed to do. The failure sits in the relay layer, the gap between a cryptographically sound protocol and what actually happens inside a browser session.
And the attack doesn't require exotic tooling. Unit 42 demonstrated that a relatively straightforward proxy setup can orchestrate the relay in real time, with latency low enough that the victim doesn't notice anything unusual during the authentication flow.
Why the Built-In Protections Fell Short
The FIDO2 spec does include defenses against this type of attack. The origin field in the authenticator response is supposed to tell the relying party which origin requested authentication. If the proxy is at evil-site.com but the challenge originated from bank.com, the mismatch should flag the session.
Unit 42's research shows these protections have gaps in practice.
The attack succeeds when the proxy can manipulate or work around origin validation. In some relying party implementations, origin checking isn't strict enough. In others, the attacker runs a reverse proxy of the legitimate site, which means the browser sees the correct origin in certain contexts because the content is actually coming from the real server.
There's a detail that's easy to miss. The origin check happens on the server side, after the authenticator has already signed the challenge. By the time the server rejects the response (if it rejects it at all), the biometric prompt has already been shown to the user. That alone has value for an attacker running a social engineering campaign. "Your fingerprint worked, so the login must be legitimate."
The crossOrigin field, introduced to help detect embedded contexts, has similar limitations. It helps in some scenarios but doesn't fully address the relay pattern that Unit 42 described.
What Developers Should Check Right Now
Here's what to audit in your WebAuthn implementation.
Strict Origin Validation
Your relying party server must validate the origin field in the authenticator response against the exact expected origin. Use a direct string comparison against your known origin. No regexes, no partial matching, no normalization tricks.
if (authenticatorResponse.origin !== "https://yourapp.com") {
reject();
}Sounds obvious. But many implementations use URL parsing libraries that normalize origins in unexpected ways, or they check against a list that includes development domains, staging URLs, or wildcard patterns. Production auth should only accept the production origin. Full stop.
Top-Level Origin Checking
The topOrigin field, available in newer WebAuthn implementations, catches cases where authentication is proxied through a subdomain or embedded frame. If your relying party doesn't check topOrigin, you're leaving a gap that the relay attack can exploit.
Not all authenticators return topOrigin yet. But when it's present and you're not validating it, that's a free vulnerability you're shipping to production.
Channel Binding
Channel binding ties the authentication to a specific TLS session. If the attacker is proxying the connection, the TLS channel binding values won't match between the victim's browser session and the attacker's session with the real server.
This is one of the stronger mitigations against relay attacks. The problem is that support across browsers and authenticators is inconsistent. Chrome has solid support. Firefox and Safari are catching up, but slowly. If your user base spans multiple browsers, you can't treat channel binding as your only defense.
Attestation and Authenticator Policy
Consider whether your application needs attestation, the process where the authenticator proves its identity and capabilities to the relying party. Attestation can help you enforce that authentication only comes from authenticators you trust, which narrows the attack surface. It won't stop relay attacks directly, but it limits what an attacker can do with a proxied session if they're also trying to register new passkeys.
Rate Limiting and Anomaly Detection on Auth Endpoints
This one gets overlooked. If someone is running a relay attack against your service, the authentication requests will have patterns. Unusual IP geolocations, session-to-auth latency anomalies, rapid successive challenge requests from the same account. Build detection for these signals. Even if you can't prevent the relay at the protocol level, you can catch it at the behavioral level.
What This Doesn't Mean
I want to be direct about something. This research doesn't mean passkeys are broken or that you should rip out your WebAuthn implementation and go back to passwords.
Passwords are still dramatically worse. The attack surface for password-based auth is enormous. Credential stuffing, phishing, brute force, database breaches, password reuse. Passkeys eliminate most of that. The "Pass the Passkey" attack requires real-time interception and is significantly harder to execute than a phishing kit you can buy for $50 on a Telegram channel.
But harder isn't impossible. And as passkey adoption grows, the incentive to develop tooling for these attacks grows with it. We've seen this exact pattern with MFA bypass kits. Push notification spam, SIM swapping, adversary-in-the-middle phishing frameworks. Each started as a proof-of-concept and evolved into commoditized attack tooling once enough targets adopted the defense.
Passkeys will follow the same trajectory if the deployment gap doesn't close.
The Deployment Gap
What Unit 42's research really exposes isn't a cryptographic weakness. It's a deployment gap.
The FIDO2 spec is theoretically solid. The problem is that real-world implementations are messy. Browsers handle WebAuthn differently. Platform authenticators behave differently across OS versions. Relying parties implement origin checking with varying strictness. And developers, understandably, follow the path of least resistance when integrating navigator.credentials.get() into their authentication flows.
We've seen this same pattern with TLS, with CORS, with CSP. The spec defines a security model. The implementation introduces cracks. Attackers find the cracks.
For developers, the takeaway is diligence. Audit your WebAuthn implementation against the checklist above. Test with relay proxies in your staging environment. Follow the FIDO Alliance's deployment guidelines and pay attention when they update them. And don't assume that "we support passkeys" means "our auth is done."
Passkeys are still the best authentication option available to most applications. But "best available" and "bulletproof" are different things. Unit 42 just showed us exactly where that line sits.



