Deleted in Signal, Preserved by iOS: The Notification Database Gap
Source: hackernews
The FBI’s recovery of deleted Signal messages from an iPhone is being framed in some coverage as a kind of cryptographic achievement, as though law enforcement cracked Signal’s end-to-end encryption. What happened is more structurally interesting: the FBI worked around Signal entirely by reading from a database that iOS maintains independently, one that Signal cannot reach and cannot clean up.
Understanding this requires a walk through how push notifications work on iOS and where the seam between Signal’s storage scope and Apple’s storage scope actually falls.
How a Signal Message Becomes a Notification
Apple Push Notification Service (APNs) is the transport layer for all push notifications on iOS. When a Signal message arrives, Signal’s servers send a small encrypted payload to APNs. APNs routes it to the recipient’s device using a device token, a 32-byte per-app per-device identifier generated when the user first registers for notifications.
The payload Signal sends to APNs does not contain plaintext. Signal uses the mutable-content flag, which triggers a mechanism Apple introduced in iOS 10 called a Notification Service Extension (NSE). Rather than displaying the notification immediately, iOS wakes a small sandboxed extension process and gives it roughly 30 seconds to modify the notification content before display.
Signal’s NSE uses this window to complete several steps: fetch the actual encrypted message envelope from Signal’s servers, access Signal Protocol decryption keys stored in a shared app group container, decrypt the message using the Double Ratchet algorithm, and call contentHandler(content) with the decrypted UNNotificationContent, setting the alert body to the plaintext message text.
A simplified version of what the NSE hands off to iOS looks like this:
override func didReceive(
_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
) {
let mutableContent = request.content.mutableCopy() as! UNMutableNotificationContent
let decryptedBody = decryptSignalMessage(request.content)
mutableContent.body = decryptedBody
contentHandler(mutableContent)
}
iOS then takes that plaintext and writes it to the system notification database before displaying the alert.
The Database Signal Cannot Touch
iOS maintains a SQLite database for delivered notifications at a path under:
/private/var/mobile/Library/UserNotifications/<app-UUID>/db2/library.db
This database stores notification payloads, delivery timestamps, thread identifiers, and the full rendered content of each notification, including the decrypted message text that Signal’s NSE produced. It is an OS-level store, separate from Signal’s own application storage. Signal does not own it and has no write access to purge records from it.
When a user deletes a message in Signal, whether through manual deletion, disappearing messages, or “Delete for Everyone,” Signal removes the record from its own SQLCipher-encrypted database. That deletion is clean and complete within Signal’s scope, but it does nothing to library.db.
The notification entry, which contains the full decrypted message text, persists in the OS database until iOS’s own garbage collection removes it. iOS does not tie notification retention to whether the originating app has deleted the corresponding content. The two systems are architecturally separate and Signal has no public API to bridge them.
Signal does call removeDeliveredNotifications(withIdentifiers:) when messages are deleted, which removes the notification from the visible Notification Center tray. But removing a notification from the tray does not guarantee the underlying database record is purged at the filesystem level, and forensic tools operate below where that API has any effect.
What Forensic Tools Extract
Tools like Cellebrite UFED, MSAB XRY, and GrayKey extract full filesystem images from iPhones when they can defeat the device lock screen. Once they have filesystem access, they parse library.db directly and present notification records in human-readable reports. The notification database has appeared as a documented source of “deleted” content in forensic work for years.
Elcomsoft, which produces competing forensic software, published analyses showing that iOS notification databases contain plaintext from Signal, WhatsApp, and Telegram, recovered after those apps had deleted the corresponding messages from their own databases. This was publicly known well before the current FBI case. Motherboard reported in 2021 on an FBI document about Cellebrite’s Signal capabilities, which noted that content could be recovered from the notification area of extracted devices. The April 2026 FBI case is, in that sense, a well-established forensic technique surfacing through a specific prosecution rather than a new capability.
The 2023 Wyden Disclosure: A Related but Separate Vector
There is a connected but distinct surveillance technique worth separating from the current case. In December 2023, Senator Ron Wyden revealed that the U.S. government had been secretly ordering Apple and Google to provide notification metadata, with the DOJ gagging both companies from disclosing these requests.
That vector concerns metadata, not content. APNs records show which device token received notifications from which app, with delivery timestamps. Apple can link a device token to an Apple ID, which maps to a real identity. This technique was used to de-anonymize users of encrypted and anonymous apps, including in investigations related to January 6 and drug trafficking cases, without ever accessing message content.
The current FBI case appears to involve content recovery from the on-device notification database, not the APNs metadata linkage approach. Both techniques exploit the same underlying infrastructure, but they answer different investigative questions and require different legal processes. The metadata approach requires a court order served on Apple; the on-device notification database approach requires physical access to the device.
Signal’s Security Model, Scoped Correctly
Signal’s encryption has not been compromised here. The Signal Protocol, which handles key exchange via Extended Triple Diffie-Hellman (X3DH) and message ratcheting via Double Ratchet, remains cryptographically sound. Signal’s servers hold no plaintext and cannot be compelled to produce message content. That part of the model works as designed.
The exposure lies at the boundary between Signal’s storage scope and the OS’s storage scope. Signal controls its own database. It does not control the iOS notification infrastructure that processes its decrypted content as a necessary step in delivering notifications to users.
Closing this gap would require one of two things: Apple providing an API for apps to purge their own notification database records at the filesystem level, which does not exist, or Signal abandoning the NSE path and relying solely on silent background push notifications. Silent push is constrained by iOS background execution limits and produces degraded notification reliability, particularly when a device has been in low-power or screen-off states. There is a genuine user experience trade-off here that Signal cannot resolve on its own. Signal has pushed for privacy improvements in how iOS handles notification content, but the OS architecture is Apple’s to change.
Data Protection Classes and the Forensic Window
The iOS notification database typically falls under the NSFileProtectionCompleteUnlessOpen data protection class. Under this class, the file is accessible whenever the device has been unlocked at least once since the last reboot. For forensic tools operating on a seized device that was unlocked at any point before seizure, this is a sufficient window for extraction.
Signal’s own message database uses stricter protection, with cryptographic keys bound to the Secure Enclave under NSFileProtectionComplete, making direct extraction substantially harder. The notification database does not share that binding. The practical consequence is that messages deleted from Signal may persist in the notification database long after the user believes they are gone, in a location that is more accessible to forensic tools than Signal’s own storage.
What Users Can Do
The most effective mitigation available right now is disabling notification previews in iOS Settings under Notifications, either globally or per-app. With previews disabled, Signal’s NSE still runs and fetches messages, but the content written to library.db contains only a generic placeholder such as “New Message” rather than the decrypted text. This trades notification detail for a meaningful reduction in forensic exposure.
Disappearing messages reduce the window during which a message exists in Signal’s own database, but they do not retroactively remove notification database entries that were already written when the message was first delivered. Regular device reboots tighten the data protection window by requiring a new unlock before files under NSFileProtectionCompleteUnlessOpen become accessible again.
The Actual Lesson
End-to-end encryption protects the transport layer and the app’s own storage. It does not protect the operating system beneath the app, which stores data by its own logic, retains it on its own schedule, and responds to different deletion signals than the application above it.
This is not a new problem. It is the same category of issue that comes up when full-disk encryption protects data at rest but leaves memory forensics viable after a warm reboot, or when a secure messaging app stores plaintext in an unprotected crash log. The cryptography is sound; the system around it has gaps, and those gaps are often larger than the cryptographic surface area.
Most users who rely on Signal for sensitive communication have not had reason to think carefully about where Signal’s security model ends and the operating system’s behavior begins. That boundary, not the encryption, is where this investigation found its opening.