WhatsApp Desktop

WhatsApp Desktop

Overview

WhatsApp Desktop on macOS stores its complete chat history as a plaintext, unencrypted SQLite database in a Group Container directory (~/Library/Group Containers/group.net.whatsapp.WhatsApp.shared/ChatStorage.sqlite). Any user-level process can read this database without Full Disk Access, without root privileges, and without any decryption keys. This is the defining forensic characteristic of WhatsApp Desktop: a messaging platform that users widely perceive as end-to-end encrypted exposes its entire local message history to any investigator with filesystem access.

This stands in direct contrast to Apple iMessage, whose database at ~/Library/Messages/chat.db requires Full Disk Access (TCC-protected). WhatsApp has no equivalent protection on the macOS Catalyst app.

WhatsApp Desktop has shipped in two distinct variants. The current native Catalyst app (net.whatsapp.WhatsApp, distributed via the Mac App Store) uses Apple's Core Data framework and stores messages in a Core Data SQLite database with ZWA-prefixed entity names. The legacy Electron app (desktop.WhatsApp, deprecated in 2024) stored data in Chromium IndexedDB/LevelDB format. This article covers the native Catalyst app. Legacy Electron storage is noted where relevant for historical cases.

The secondary data source is the iCloud backup located at ~/Library/Mobile Documents/57T9237FN3~net~whatsapp~WhatsApp/Accounts/<phone>/backup/. This directory contains AES-encrypted .enc database files (requiring the user's E2E backup key to decrypt) alongside unencrypted .tar archives containing media, documents, and thumbnails. Investigators can access the tar archives without any decryption keys.

The Critical Finding: Plaintext Group Container

The native WhatsApp Catalyst app is distributed as a sandboxed Mac App Store application, but it uses a shared App Group container (group.net.whatsapp.WhatsApp.shared) rather than its private sandbox container. App Group containers in ~/Library/Group Containers/ are accessible to any process running as the same user — they are specifically designed for inter-process data sharing. WhatsApp uses this mechanism to share the chat database with its notification extension (net.whatsapp.WhatsApp.ServiceExtension), but as a consequence, any user-level process on the system can read ChatStorage.sqlite without any TCC permission prompt or Full Disk Access.

No Full Disk Access Required

Unlike Apple Messages (chat.db), iMessage attachments, or Mail databases, WhatsApp's ChatStorage.sqlite requires only standard user-level read permissions. A collection tool running as the logged-in user can read the full chat history without any TCC approval or elevated privileges. This has been documented by security researcher Mysk (@mysk_co) in July 2024.

Forensic implication: WhatsApp's end-to-end encryption protects messages in transit. It does not protect messages at rest on the local macOS filesystem. An investigator with physical access to the device, a forensic image, or a live acquisition running as the user has direct access to the complete plaintext message history.

File Locations

Native Catalyst App (Primary)

ArtifactPathFormatNotes
Live chat database~/Library/Group Containers/group.net.whatsapp.WhatsApp.shared/ChatStorage.sqliteSQLite (plaintext)Primary forensic artifact — no encryption
Chat database WAL~/Library/Group Containers/group.net.whatsapp.WhatsApp.shared/ChatStorage.sqlite-walSQLite WALUncommitted transactions — always collect
Chat database SHM~/Library/Group Containers/group.net.whatsapp.WhatsApp.shared/ChatStorage.sqlite-shmSQLite SHMShared memory file
Full-text search index~/Library/Group Containers/group.net.whatsapp.WhatsApp.shared/ChatSearch.sqliteSQLite FTSMay retain text from deleted messages
Search WAL~/Library/Group Containers/group.net.whatsapp.WhatsApp.shared/ChatSearch.sqlite-walSQLite WAL

iCloud Backup (Secondary)

The iCloud backup path encodes both the App Team ID and bundle ID: 57T9237FN3~net~whatsapp~WhatsApp. Account directories are named with the full phone number including country code (e.g., 14155551234).

ArtifactPathFormatNotes
Backup metadata~/Library/Mobile Documents/57T9237FN3~net~whatsapp~WhatsApp/Accounts/<phone>/backup/Backup.plistPlistUnencrypted — size inventory, date, version
Chat database (encrypted)…/backup/ChatStorage.sqlite.encAES encryptedRequires E2E backup key
Call history (encrypted)…/backup/CallHistory.sqlite.encAES encryptedRequires E2E backup key
Key-value store (encrypted)…/backup/BackedUpKeyValue.sqlite.encAES encryptedCryptographic keys and account data
Search index (encrypted)…/backup/ChatSearch.sqlite.encAES encryptedRequires E2E backup key
Extended chat data (encrypted)…/backup/ExtChatDatabase.sqlite.encAES encrypted
Media archive…/backup/Media.tarTarUnencrypted — images and attachments
Video archive…/backup/Video.tarTarUnencrypted — video files
Document archive…/backup/Document.tarTarUnencrypted — shared documents
GIF archive…/backup/GIFs.tarTarUnencrypted
Sticker archive…/backup/Stickers.tarTarUnencrypted
Thumbnail archive…/backup/Thumbnail.tarTarUnencrypted — image thumbnails

Unencrypted Tar Archives

The .tar archives in the iCloud backup directory are not encrypted, regardless of whether the user has enabled end-to-end encrypted backups. Media files, documents, and thumbnails can be extracted from these archives without any decryption keys.

Extension Containers

ArtifactPathNotes
Notification media~/Library/Containers/net.whatsapp.WhatsApp.ServiceExtension/Data/tmp/documents/JPEG thumbnails for incoming message notifications
Service extension preferences~/Library/Containers/net.whatsapp.WhatsApp.ServiceExtension/Data/Library/Preferences/net.whatsapp.WhatsApp.ServiceExtension.plist

Legacy Electron App Paths (Deprecated)

ArtifactPathFormat
Message data (IndexedDB)~/Library/Containers/desktop.WhatsApp/Data/Library/Application Support/WhatsApp/IndexedDB/LevelDB
Chromium cache~/Library/Containers/desktop.WhatsApp/Data/Library/Application Support/WhatsApp/Cache/Chromium cache
Application log~/Library/Containers/desktop.WhatsApp/Data/Library/Application Support/WhatsApp/main-process.logText

Application Variants

PropertyNative Catalyst (Current)Electron (Deprecated)
Bundle IDnet.whatsapp.WhatsAppdesktop.WhatsApp
DistributionMac App StoreDirect download (.dmg)
macOS minimum11.010.15
Storage formatCore Data SQLiteChromium IndexedDB / LevelDB
Database location~/Library/Group Containers/group.net.whatsapp.WhatsApp.shared/~/Library/Containers/desktop.WhatsApp/
EncryptionNone (plaintext)None (plaintext)
iCloud backupYesNo
StatusActive (2024–present)Deprecated (2024)

WhatsApp JID Format

WhatsApp uses XMPP-derived Jabber IDs (JIDs) to identify all entities. JIDs appear throughout the database in ZFROMJID, ZTOJID, ZCONTACTJID, ZMEMBERJID, and ZRECEIPTJID columns.

JID FormatEntity TypeExample
<phone>@s.whatsapp.netIndividual contact14155551234@s.whatsapp.net
<id>@g.usGroup chat120363123456789012@g.us
<phone>@broadcastBroadcast list14155551234@broadcast
status@broadcastStatus updatesstatus@broadcast

The phone number in @s.whatsapp.net JIDs is the full E.164 international number without the leading + sign. 14155551234 represents +1-415-555-1234. Phone numbers can be extracted directly from JIDs without any additional lookup, enabling identity attribution across the dataset.

Account directories in the iCloud backup path follow the same format — a directory named 14155551234 belongs to that phone number.

Core Data Schema Overview

The native Catalyst app uses Apple Core Data with the following primary entities (tables). All table names carry the ZWA prefix from Core Data code generation.

TablePurpose
ZWAMESSAGEAll messages — text, media references, delivery status
ZWACHATSESSIONConversation threads — 1:1, group, broadcast
ZWAMEDIAITEMMedia attachment metadata — paths, URLs, MIME types, dimensions, geolocation
ZWAGROUPINFOGroup metadata — name, description, creator
ZWAGROUPMEMBERGroup membership — JIDs, admin roles
ZWAMESSAGEINFOPer-recipient delivery and read receipts
ZWAPROFILEPUSHNAMEContact display names as set by the contact
ZWAPROFILEPICTUREITEMContact avatar metadata
ZWAMESSAGEDATAITEMExtended message data for vCards and structured content
ZWAGROUPMEMBERSCHANGEGroup membership change event log
ZWAVCARDMENTIONContacts mentioned within messages
Z_PRIMARYKEYCore Data internal — entity type registry and record counts
Z_METADATACore Data internal — model version hash

See Chat Database for complete table schemas and SQL queries.

Timestamp Format

All timestamp columns in the native Catalyst app use the Apple Core Data epoch: seconds (floating-point) since January 1, 2001, 00:00:00 UTC. This is the same epoch used by iMessage, FaceTime, Apple Contacts, and all other Core Data applications.

Conversion formula:

unix_timestamp = core_data_timestamp + 978307200

Example:

Core Data value:  764553600.0
+ 978307200
= Unix timestamp: 1742860800
= 2025-03-24 00:00:00 UTC

SQL conversion:

-- Convert a Core Data timestamp to ISO 8601 in SQLite
SELECT datetime(ZMESSAGEDATE + 978307200, 'unixepoch') AS message_time
FROM ZWAMESSAGE;

Zero values in timestamp columns indicate the timestamp was not set. Null values indicate the column was not applicable (e.g., ZSENTDATE is null for received messages).

Key Artifacts

Chat Database (ChatStorage.sqlite)

The primary forensic artifact. Contains the complete local message history in plaintext — message text, sender JIDs, delivery status, media references, group membership, and read receipts. Accessible without encryption or Full Disk Access. See Chat Database for schema documentation.

Full-Text Search Index (ChatSearch.sqlite)

An FTS (Full-Text Search) database that WhatsApp maintains alongside the main database. The search index may retain indexed text from messages that have since been deleted from ChatStorage.sqlite, making it a potential source for deleted message recovery.

iCloud Backup Directory

A second copy of the chat data synced to iCloud. The SQLite databases are AES-encrypted and require the user's end-to-end backup key to decrypt. However, the .tar archives containing media files are unencrypted and accessible immediately. The Backup.plist metadata file provides size inventory and backup timestamps. See iCloud Backup.

Notification Extension Media

The ServiceExtension container may hold JPEG thumbnail images for incoming message notifications. These can provide visual evidence of media shared in conversations even when the main chat database is unavailable.

macOS Version Support

macOS VersionNative CatalystElectron (Legacy)Notes
10.15 CatalinaNot supportedFullElectron only era
11.0 Big SurFullFull (deprecated later)Catalyst requires macOS 11+
12.0 MontereyFullAvailable
13.0 VenturaFullDeprecatedWhatsApp began deprecation process
14.0 SonomaFullEnd-of-lifeUsers prompted to switch to native
15.0 SequoiaFullNot supportedNative app only

The Core Data schema is driven by WhatsApp application releases, not macOS versions. Schema column additions occur with WhatsApp app updates and may add columns for features such as message editing, view-once media, disappearing messages, or WhatsApp Channels.

Forensic Analysis Notes

  • Phone number attribution is direct: JIDs encode full E.164 phone numbers. Cross-reference @s.whatsapp.net JIDs with Contacts (contacts.addressbook) to resolve names without requiring a WhatsApp account lookup.
  • Delivery receipts are per-recipient: ZWAMESSAGEINFO stores a separate row for each group member who received or read the message. For outgoing group messages, ZMESSAGESTATUS on the ZWAMESSAGE row reflects aggregate delivery state, while ZWAMESSAGEINFO provides individual recipient confirmation.
  • Forwarded messages: The ZISFORWARDED flag on ZWAMESSAGE indicates a message was forwarded from another conversation. The ZFORWARDCOUNT column tracks how many times the message has been forwarded. This is significant for disinformation or data exfiltration investigations.
  • Starred messages: ZSTARRED = 1 marks messages the user explicitly saved. Starred messages often indicate content the user considered important.
  • Archived chats: ZWACHATSESSION.ZARCHIVED = 1 indicates the user archived a conversation. Archived chats are hidden from the default view but remain in the database.
  • Disappearing messages: ZWACHATSESSION.ZDISAPPEARINGMESSAGEDURATION sets the auto-delete timer. Individual messages already deleted by the timer are removed from the database — but the conversation record remains and the ZMESSAGECOUNTER still reflects the historical total.
  • WAL mode: ChatStorage.sqlite operates with SQLite WAL mode. Always collect ChatStorage.sqlite-wal and ChatStorage.sqlite-shm alongside the main file to capture all committed transactions.
  • Record counts from Z_PRIMARYKEY: The Core Data Z_PRIMARYKEY table's Z_MAX column reflects the highest primary key value ever assigned for each entity type. This acts as a lower bound on the total number of messages or sessions ever created, regardless of how many remain in the active tables.

Deleted Message Recovery

SQLite does not immediately overwrite freed pages when rows are deleted. WhatsApp message text, JIDs, and other string data may persist in SQLite free pages after deletion. The ChatSearch.sqlite FTS index may also retain indexed text from deleted messages. See Deleted Messages for recovery techniques.

Tool Support

ToolSupport Level
macforFull collection: messages, conversations, iCloud backup enumeration, media tar extraction, deleted message recovery
AXIOMWhatsApp Desktop support
CellebriteWhatsApp Desktop support
DB Browser for SQLiteManual analysis — open ChatStorage.sqlite directly
sqlite3 CLIDirect query access

References

Previous
Sessions & Secret Chats