---
url: 'https://www.corbado.com/blog/signal-api-ios-passkey-deletion-bug'
title: 'Signal API iOS Bug: Passkeys of Other Accounts Deleted'
description: 'On iOS and macOS 26 the WebAuthn Signal API deletes passkeys of unrelated accounts. Our reproduction, the affected methods and the trade-off you face.'
lang: 'en'
author: 'Vincent Delitz'
date: '2026-08-21T16:17:00.710Z'
lastModified: '2026-08-21T16:44:37.374Z'
keywords: 'signal api passkey deletion, signalAllAcceptedCredentials bug, webauthn signal api ios, signalUnknownCredential deletes passkeys, apple passwords app bug, passkey deleted ios 26, ASCredentialUpdater'
category: 'WebAuthn Know-How'
---

# Signal API iOS Bug: Passkeys of Other Accounts Deleted

## Key Facts

- On **iOS and macOS 26** the WebAuthn Signal API removes passkeys it was never called for:
  `signalAllAcceptedCredentials` and `signalUnknownCredential` can delete the passkey of a
  **different account on the same RP ID**, whose user handle is never passed to the API.
- The affected account has to be stored as a **combined password and passkey entry** in the
  Passwords app, which only happens when the password was saved through the iOS **system save
  prompt**. A password added manually inside the Passwords app does not trigger it.
- **Only the two removal methods are affected.** `signalCurrentUserDetails`, which updates the
  user name, stays correctly scoped. The same split holds for the native counterparts
  `reportAllAcceptedPublicKeyCredentials` and `reportUnknownPublicKeyCredential`.
- Reproduced on **iOS 26.0.1, 26.5 and 26.6.1**, so the behavior has been present since the
  Signal API shipped with iOS 26.0 in September 2025. There is no fix at the time of writing.
- Deleted passkeys stay recoverable in the **Deleted section of the Passwords app for 30 days**,
  and nothing tells the user, so affected users silently fall back to password login.

## 1. Introduction

While adding [WebAuthn Signal API](https://www.corbado.com/blog/webauthn-signal-api) support to our iOS SDK we found a
bug in Apple's Passwords app: deleting a passkey for one account can delete the passkey of a
completely different account. The user handle of that other account is never passed to the API.

This is not a regression in a recent update. We reproduced it on iOS 26.0.1 as well as on 26.5
and 26.6.1, so it has been there since the Signal API shipped with [iOS 26](https://www.corbado.com/blog/ios-26-passkeys).0
in September 2025. A [similar report](https://bugs.webkit.org/show_bug.cgi?id=302624) has been
open since November 2025 without a response, and we filed
[our own bug](https://bugs.webkit.org/show_bug.cgi?id=322267) with a full reproduction on August
21, 2026. There is no fix yet.

In this article, we answer:

1. **What exactly happens?** Which passkeys get deleted and under which conditions.
2. **Which of the three signal methods are affected?** We tested all of them against the same
   setup.
3. **What should you do about it?** Which trade-off you face, and why we still recommend using
   the Signal API.

## 2. Signal API in a nutshell

The Signal API lets a relying party tell the [passkey provider](https://www.corbado.com/blog/passkey-providers) what the
server-side truth is, so that stale passkeys stop showing up in
[Conditional UI](https://www.corbado.com/blog/webauthn-conditional-ui-passkeys-autofill). It has three methods, and the
distinction between them matters for this bug:

| Method | Scoped by | What it does |
| :--- | :--- | :--- |
| `signalCurrentUserDetails` | rpId + user handle | updates the user name shown for a passkey |
| `signalAllAcceptedCredentials` | rpId + user handle | removes passkeys not in the list you pass |
| `signalUnknownCredential` | rpId + credential ID | removes one specific passkey |

Two of them remove credentials, one only updates metadata. All three exist natively as well, in
`ASCredentialUpdater` (iOS 26.0) and its successor `ASCredentialDataManager` (iOS 26.2), so
[native apps](https://www.corbado.com/blog/native-app-passkeys) are just as exposed as websites.

The scoping is not an implementation detail, it is the whole contract. WebAuthn Level 3 defines
the behavior of `signalAllAcceptedCredentials` on `credentials map[rpId, userId]`, which means one
account, and Apple's native signature takes a `userHandle` for exactly that reason.

## 3. What we observe on iOS and macOS 26

### 3.1 Setup

The reproduction needs two accounts on the same RP ID with different user names and different user
handles:

- **account1**: has a passkey
- **account2**: has a passkey and a password

One detail decides whether the bug appears: the password of account2 must have been saved through
the **system save prompt**, the sheet iOS shows after a successful password login. A password that
was added manually inside the Passwords app does not trigger it. The reason is what that prompt
produces: when a password and a passkey exist for the same site with the same user name, the
Passwords app combines them into a single entry.

{/* VISUAL TODO: screenshot of the Apple Passwords app entry list for the test RP ID, before any
signal call, showing account1 as a passkey-only entry and account2 as one combined password and
passkey entry. Pull the frame from the screen recording filed with WebKit bug 322267, then upload
with `cd apps/cli && bun upload-image --input <path> --output markdown` and embed the S3 URL. A
repo path under /images/ renders nothing. */}

### 3.2 What happens

We sign in as account1, delete its passkey server side and signal that to the device:

```javascript
await PublicKeyCredential.signalAllAcceptedCredentials({
    rpId: 'example.com',
    userId: '<user handle of account1>',
    allAcceptedCredentialIds: [], // account1 has no passkeys left
});
```

Only account1 is referenced. In the Passwords app we then see:

- account1's passkey is deleted, which is correct
- account2's passkey is deleted as well, although its user handle was never passed
- account2's password survives, only the passkey is gone

The Deleted section of the Passwords app makes this very visible. Before the call it is empty,
after the call it holds two passkeys for the same site, one for each account. Deleted passkeys stay
recoverable there for 30 days, and nothing informs the user that anything happened.

![Apple Passwords Recently Deleted before and after the signalAllAcceptedCredentials call: empty beforehand, then two deleted passkeys, one for the signalled account test+20 and one for the unrelated account test+13](https://s3.eu-central-1.amazonaws.com/corbado-cloud-staging-website-assets/shot_deleted_before_after_d022c0f521.png)

## 4. Which signal methods are affected

Our first assumption was that the user handle gets lost for passkeys inside a combined entry, so
that the lookup falls back to matching the RP ID only. To check that, we added all three methods
to our iOS SDK and ran them against the same two accounts.

| Method | Scoped by | What it does | Touches other accounts |
| :--- | :--- | :--- | :--- |
| `signalCurrentUserDetails` | rpId + user handle | updates metadata | no |
| `signalAllAcceptedCredentials` | rpId + user handle | removes | **yes** |
| `signalUnknownCredential` | rpId + credential ID | removes | **yes** |

Group the results by the key a method matches on and nothing lines up: the two methods that use
rpId plus user handle behave differently from each other. Group them by what they do and the
picture is clean. **Both methods that remove a credential reach into other accounts, the one that
only updates metadata does not.**

That rules out our first assumption. `signalCurrentUserDetails` uses the same rpId plus user handle
lookup, on the same entries, and it lands exactly on account1. The association between a passkey
and its user handle is therefore intact and can be queried correctly.

The result for `signalUnknownCredential` is even stronger, because that method matches on an exact
credential ID. WebAuthn Level 3 defines its authenticator action as walking the credential map and
removing the credential whose rpId **and** id both match. There is no reading of "remove this one
credential ID" that legitimately reaches a credential of a different account. Yet it does, and
again only the passkey part of the combined entry disappears while the password stays.

Our conclusion: the matching works, but the removal is applied to something coarser than the single
matched credential, most likely to the Passwords entry or to the set of entries resolved for the RP
ID. That would also explain the older report about `signalUnknownCredential` removing credentials
that were never specified.

## 5. Impact for relying parties

The bug only fires when a signal call actually removes a passkey for the signalled account. As
long as the list you send matches what the device holds, nothing is deleted and no other account is
touched. The failure mode is quiet, which is what makes it expensive:

- **Users lose a working passkey for an account you never signalled about.** They find out at their
  next login, when the passkey is simply gone.
- **Nothing surfaces to you.** Signal methods deliberately return no information about what the
  authenticator did, so there is no error to log and no callback to observe.

![iOS notification reading Passkey Deleted, ConnectExample removed a passkey for test+20@example.com, naming only the signalled account while the second account's passkey was removed without any notice](https://s3.eu-central-1.amazonaws.com/corbado-cloud-staging-website-assets/shot_passkey_deleted_notification_094c8efff2.png)

- **It only hits multi-account users.** Anyone with a private and a work login, family members
  sharing a device, retail or banking customers with several accounts. You cannot measure that
  population from your backend, because what matters is which accounts share one Apple ID.
- **Recovery exists but is invisible.** The passkey sits in Passwords under Deleted for 30 days.
  Almost nobody will look there.

In your own data this shows up as an unexplained shift from passkey login back to password login,
which is only visible if you measure your [login funnels](https://www.corbado.com/blog/webauthn-errors) per method.

## 6. Trade-off you have to make

Before weighing the options, one property of the bug matters more than anything else: **it is
triggered by deletions, not by calls**. If you call `signalAllAcceptedCredentials` after every
login and the credential IDs you send match what the device holds, nothing is removed and no other
account is affected. Only the calls that really delete a passkey for the signalled account can take
a second account's passkey with them. Calling more often does not increase your exposure, deleting
more passkeys does.

That puts both sides of the trade-off on the same event: a passkey that is removed on your server.

**Option A: stop calling the removal methods.** Passkeys that users delete on your server stay in
the Passwords app. They keep being offered in Conditional UI, users pick them, and the login fails.
That is exactly the stale credential problem the Signal API was built to solve, and a passkey that
fails at login is one of the most reliable ways to make someone give up on passkeys for good. This
hits every user who deletes a passkey, and it hits them at the worst possible moment.

**Option B: keep calling them.** For each passkey you delete server side, a user who also has a
second account on the same RP ID, under the same Apple ID, stored as a combined password and
passkey entry, silently loses that second passkey. Worse per incident, but it needs several
conditions to line up at once.

**Our recommendation is to keep using the Signal API.** For most relying parties the stale
credential problem is the far more common situation: it affects everyone who deletes a passkey,
while the cross-account deletion needs a second account, the same Apple ID and a combined entry
created by the system save prompt. Trading a frequent, visible failure at login for a rare one is
the better deal today. If multiple accounts per person are the norm in your product rather than the
exception, run the numbers again, because then the picture can flip.

A few practical points either way:

- keep `signalCurrentUserDetails`, it is correctly scoped and it solves a real problem with stale
  user names
- both removal methods are affected in the same way, so there is no safer one of the two to switch
  to
- never send an empty `allAcceptedCredentialIds` unless you really mean "remove everything for this
  user", because that is a deletion and therefore triggers the bug
- no change for [Chrome](https://www.corbado.com/blog/client-hints-user-agent-chrome-safari-firefox) and Google Password
  Manager, where the effect is hiding rather than deleting and can be reversed
- brief your support team: Passwords, then Deleted, within 30 days

## 7. Status and next steps

We filed [WebKit bug 322267](https://bugs.webkit.org/show_bug.cgi?id=322267) with a full
reproduction and a screen recording. The WebKit tracker is public and the WebAuthn owners can be
reached there, which is why we chose it, even though the defect is not in WebKit: WebKit only
forwards the call to `ASCredentialDataManager`, so the fix has to happen in AuthenticationServices
and the Passwords app.

The open question we put to Apple is whether the removal is implemented on entry level instead of
on credential level. We will update this article as soon as there is a response or a fixed
version.

## 8. How Corbado can help

This bug never reaches your backend. The signal methods return nothing, the passkey disappears on
the device and the only trace left is a user who quietly logs in with a password again.
[Corbado Observe](https://www.corbado.com/observe) is the authentication observability layer that makes that shift
visible, on the login flow you already run today.

[Video: Login methods](https://www.corbado.com/videos/features/login-methods.mp4)

- **Login Methods** shows the passkey and password split per method with success, failure and
  cancel rates, so a drop in passkey logins surfaces as a trend rather than a support ticket.
- **Technology** breaks the same outcomes down by OS and browser, which is what separates an
  iOS 26 regression from everything else happening on your login page.
- **Passkey Insights** tracks your credential population by authenticator, transport and sync
  status, so passkeys that vanish from devices show up as a shrinking inventory.
- **User Search** reconstructs a single user's authentication timeline, which is how you confirm
  that a working passkey stopped being offered between two sessions.

Telemetry is UUID only with zero PII by design, hosted in EU data centers.

## 9. Conclusion

The Signal API is still the right tool for keeping passkeys in sync between your server and your
users' devices, and we are not arguing against adopting it. But the client side of passkeys is
where the sharp edges are, and this one is sharp: a documented, user handle scoped API that removes
credentials outside that scope, silently, on the most common passkey platform.

- **What is broken?** Both signal methods that remove a credential can delete passkeys of other
  accounts on the same RP ID, if those accounts are stored as a combined password and passkey entry
  in the Passwords app.
- **What still works?** `signalCurrentUserDetails` is correctly scoped, and non-Apple platforms are
  not affected in the same way.
- **What can you do?** In our view, keep using the Signal API: stale passkeys in Conditional UI
  hurt more users far more often than this bug does. Make sure your support team knows about the
  Deleted section of the Passwords app.

## Frequently Asked Questions

### Does signalAllAcceptedCredentials delete passkeys of other accounts on iOS?

Yes. On iOS and macOS 26 a call to `PublicKeyCredential.signalAllAcceptedCredentials()` for one
account can delete passkeys of a different account on the same RP ID, if that other account is
stored as a combined password and passkey entry in the
[Passwords app](https://www.corbado.com/blog/how-to-use-apple-passwords). The user handle of the affected account is never
passed to the API, so this contradicts both the WebAuthn specification and Apple's own API
signature, which is scoped to a user handle.

### Which WebAuthn Signal API methods are affected on iOS?

Both methods that remove a credential are affected: `signalAllAcceptedCredentials` and
`signalUnknownCredential`. `signalCurrentUserDetails`, which only updates the user name of a
passkey, is correctly scoped and does not touch credentials of other accounts. This holds for the
web methods as well as for their native counterparts `reportAllAcceptedPublicKeyCredentials` and
`reportUnknownPublicKeyCredential` in AuthenticationServices.

### Which iOS versions are affected by the Signal API passkey deletion bug?

All iOS and macOS 26 versions we tested, from 26.0.1 up to 26.6.1. This is not a regression in a
later point release. The Signal API shipped with iOS 26.0 in September 2025 and the behavior has
been present since then. There is no fix available at the time of writing.

### Can users recover a passkey that was deleted by the Signal API?

Yes, for 30 days. Deleted passkeys are moved to the Deleted section of the Passwords app and are
permanently removed after 30 days. The problem is that nothing tells the user that a passkey was
removed, so most affected users will never look there and will simply fall back to
[password login](https://www.corbado.com/blog/how-to-delete-passkey-apple-windows-android).
