How to read this
- Entry type
- Evidence review
- Sources verified
- 10/19/2026
- Evidence classes
- practitioner note
This entry reviews evidence published by other people. The author did not test any tool or examine any device for it. Blocks marked with an evidence class quote or summarize a source; sentences beginning “we” describe what the author did with those sources, which was to read them. Anything DEVI could not confirm is marked as such and left as an open question rather than written up as a finding. Sources change without notice, which is why the verification date is stated.
Apple's Messages app is reported to keep iMessage, SMS, and RCS in one SQLite database. This page restates two public notes. It is not a test of a phone, and Apple does not publish this schema as a specification in either note.
What the record shows
The thread on screen is the join. A message row does not, by itself, name the conversation. Both notes reach the conversation through chat_message_join.
Where it lives
The SHA-1 of the string HomeDomain-Library/SMS/sms.db is 3d0d7e5fb2ce288813306e4d4636395e047a3d28. That is the hash of the string. It does not prove a given backup contains the file.
The same note says the database is often accompanied by chat.db-wal and chat.db-shm on a Mac, and that new rows can sit in the WAL until SQLite folds them into the main file. Copying the main file alone can miss the newest messages. The note's own copy commands are not repeated here.
How to read it
Both notes treat the file as ordinary SQLite once you have it. The MessagingForensics note says to check PRAGMA table_info(message) before relying on a column, because column availability depends on the OS version. Encrypted backups have to be decrypted with the backup password before the file is plain SQLite. That limit is the note's, and this page does not add a method.
On a Mac, both notes say privacy controls can block the folder until Full Disk Access is granted. That is a macOS privacy setting, not a forensic step invented here.
What the fields mean
These are the message columns the 09/25/2026 note lists. It also says not every database has every column.
ROWID: the local integer other tables point at.guid: the stable id reactions and replies point at.text: the message text, when it is stored there.attributedBody: a blob that holds the text whentextis null.handle_id: the remote party, intohandle. The note says it may be 0 on some outgoing group rows.is_from_me: direction. The note uses it as the outgoing flag.service: the transport. The note namesiMessage,SMS, andRCSon recent versions.date,date_read,date_delivered,date_edited,date_retracted: Cocoa times. A zero in a read or delivered column means not recorded, not 01/01/2001.associated_message_typeandassociated_message_guid: a reaction row points at the message it reacts to.thread_originator_guid: the note calls this the reply reference.
handle.id is a phone number or an email address, plus a service. chat carries chat_identifier, display_name for a group name, and service_name. attachment carries filename, transfer_name, mime_type, and total_bytes. The joins are chat_message_join and message_attachment_join.
The Atomic Object note uses the same join to list messages and warns that, on a recent Mac, text may be empty because the body moved to attributedBody. It is unsure of the macOS version and says "Ventura I think." The September 2026 note is more definite: macOS Ventura and later, and the matching iOS versions.
Pitfalls
Timestamps changed unit. The September 2026 note says older databases store seconds and newer ones store nanoseconds, with the change around macOS High Sierra and iOS 11. It says a 9-digit value is seconds and an 18-digit value is nanoseconds, both counting from 01/01/2001 00:00:00 UTC. Dividing a seconds value as if it were nanoseconds, or the reverse, produces a wrong time.
text can be null while the conversation is still in attributedBody. A query that reads only text under-reports those rows. The note says the blob is a legacy typed stream beginning with streamtyped, and that pulling the first string out of it is not a full decode.
Reactions are rows. The note maps 2000 through 2005 to the six classic tapbacks and 3000 through 3005 to removing them, and it says later releases added further codes. Counting every message row as a message counts the reactions too.
Edits and unsends, since iOS 16 and macOS Ventura in that note, use date_edited and date_retracted. The visible text is the latest version. The note says earlier wording is kept in other structures whose format is not documented, so a reconstructed original is tool-dependent. An unsent row can remain after the content is gone.
The WAL can hold the newest change. A database opened without its WAL is an older state, and the main file does not advertise the gap.
How it holds up in court
A message row is evidence of what that file contained, after someone shows where the file came from and that the reading did not change it. It is not, by itself, proof of who typed the words, or of what a court will admit.
Not independently verified
No holding about sms.db, chat.db, tapbacks, or attributedBody was read for this page. Column lists above are the public notes, checked 10/19/2026, not a schema Apple published and not a phone examined for this entry.
Search, passcodes, and provider data are a separate source review: The Legal Questions Around Mobile Device Extraction Are Not One Question.