Overview
The macOS Calendar application (formerly iCal) stores all calendar data in a SQLite database called "Calendar Cache". This Core Data store contains events, attendees, locations, recurrence rules, alarms, and account synchronisation state across all configured calendar accounts (iCloud, Google, Exchange, CalDAV). Individual calendar events are also stored as ICS files on disk.
Forensic Significance
| Evidence Type | Forensic Value |
|---|
| Event details | Meeting subjects, descriptions, and notes |
| Attendees | People invited to or attending meetings |
| Locations | Physical and virtual meeting locations |
| Time ranges | When events were scheduled (including timezone) |
| Recurrence | Recurring meeting patterns (daily standups, weekly meetings) |
| Event creation/modification | When events were created or changed |
| Account sources | Which calendar services are configured (iCloud, Google, Exchange) |
| Deleted events | Recently deleted calendar events |
File Locations
| Artifact | Path | Format |
|---|
| Calendar Cache | ~/Library/Calendars/Calendar Cache | SQLite (Core Data) |
| WAL file | ~/Library/Calendars/Calendar Cache-wal | SQLite WAL |
| SHM file | ~/Library/Calendars/Calendar Cache-shm | SQLite SHM |
| ICS events | ~/Library/Calendars/<UUID>.calendar/Events/*.ics | ICS text |
| Calendar metadata | ~/Library/Calendars/<UUID>.calendar/Info.plist | Plist |
Database Schema
The Calendar Cache is a Core Data SQLite store. Key entities:
ZCALENDARITEM (Events and Reminders)
| Column | Type | Description |
|---|
Z_PK | INTEGER | Primary key |
Z_ENT | INTEGER | Entity type (16=event, 17=reminder) |
ZTITLE | TEXT | Event title/subject |
ZLOCATION | TEXT | Event location |
ZNOTES | TEXT | Event description/notes |
ZSTARTDATE | REAL | Start time (Core Data timestamp) |
ZENDDATE | REAL | End time (Core Data timestamp) |
ZCREATEDDATE | REAL | When the event was created |
ZLASTMODIFIEDDATE | REAL | When the event was last modified |
ZCALENDAR | INTEGER | Foreign key to calendar |
ZISALLDAY | INTEGER | Whether this is an all-day event |
ZISDETACHED | INTEGER | Whether this is a detached recurrence instance |
ZTIMEZONE | INTEGER | FK to timezone |
ZRECURRENCERULE | INTEGER | FK to recurrence rule |
ZATTENDEE
| Column | Type | Description |
|---|
ZCOMMONNAME | TEXT | Attendee display name |
ZADDRESS | TEXT | Email address (typically mailto: URI) |
ZSTATUS | INTEGER | Attendance status (accepted, declined, tentative) |
ZROLE | INTEGER | Role (required, optional, chair) |
ZEVENT | INTEGER | FK to event |
ZCALENDAR
| Column | Type | Description |
|---|
ZTITLE | TEXT | Calendar name |
ZEXTERNALID | TEXT | External identifier |
ZSOURCERELATIVEURL | TEXT | Account source URL |
Key Fields for Analysis
Essential Query
SELECT
ci.ZTITLE AS title,
ci.ZLOCATION AS location,
datetime(ci.ZSTARTDATE + 978307200, 'unixepoch') AS start_time,
datetime(ci.ZENDDATE + 978307200, 'unixepoch') AS end_time,
ci.ZNOTES AS notes,
c.ZTITLE AS calendar_name
FROM ZCALENDARITEM ci
LEFT JOIN ZCALENDAR c ON ci.ZCALENDAR = c.Z_PK
WHERE ci.Z_ENT = 16
ORDER BY ci.ZSTARTDATE DESC;
Events with Attendees
SELECT
ci.ZTITLE AS event,
datetime(ci.ZSTARTDATE + 978307200, 'unixepoch') AS start_time,
a.ZCOMMONNAME AS attendee,
a.ZADDRESS AS email
FROM ZCALENDARITEM ci
JOIN ZATTENDEE a ON a.ZEVENT = ci.Z_PK
WHERE ci.Z_ENT = 16
ORDER BY ci.ZSTARTDATE DESC;
Timestamps
Calendar uses Core Data timestamps (seconds since 2001-01-01 00:00:00 UTC).
Unix timestamp = core_data_timestamp + 978307200
Analysis Notes
- Meeting reconstruction: Combine event titles, locations, attendees, and notes to reconstruct meeting activity and identify who the user met with.
- Location tracking: Calendar event locations (both physical addresses and virtual meeting URLs like Zoom/Teams links) reveal movement patterns and communication tools used.
- Account enumeration: The calendar accounts configured on the system reveal organisational affiliations (Exchange accounts indicate employer, Google accounts may be personal).
- ICS files: Individual
.ics files in the calendar directories contain event data in a text format that may include information not present in the SQLite cache. - Deleted events: Core Data soft-deletes may leave traces of removed events in the database.
- Timezone analysis: Event timezones combined with creation timestamps can indicate where the user was when they created the event.
Version Differences
| macOS Version | Changes |
|---|
| 10.8+ | Calendar Cache SQLite format (Core Data) |
| 10.15 (Catalina) | Additional metadata fields |
| 13 (Ventura) | Enhanced iCloud sync metadata |
| Tool | Support |
|---|
| macfor | Not yet implemented (planned) |
| sqlite3 | Manual database inspection |
| Calendar.app (macOS built-in) | GUI calendar viewer |
| mac_apt | Open-source calendar parser |
References