Crash Reports: macOS DiagnosticReports (.ips)
macOS crash and diagnostic reports record which binary crashed, its path, parent, signing identity, launch and crash time, even for malware.
- Location
- /Library/Logs/DiagnosticReports/
- Proves
- That a given executable ran on the Mac, from which path, launched by which parent, and when it crashed or hung
- Timestamps
- Local time with UTC offset in JSON strings and file names
- Access
- root, or membership of _analyticsusers (admins are members)
- Retention
- Moved to Retired and cleaned up by SubmitDiagInfo; days to weeks
- Collection
- Aftermath, UAC, sysdiagnose, ditto
Tools
Compare all tools- jqCLI · built into macOS
- mac_aptCLI · open source
- ConsoleGUI · built into macOS
What it is
When a process crashes, hangs or exceeds a resource limit, macOS writes a diagnostic report. Since macOS 12 Monterey, crash reports are JSON documents with an .ips extension; earlier releases wrote plain-text .crash files. Console presents both in the same human-readable layout.
For an investigator, a crash report is proof of execution with rich context: the full executable path, the parent process, code-signing identity, the loaded libraries and exact launch and crash times. Malware, droppers and exploit attempts crash more often than polished software, and the report can outlive the binary.
Where it lives
| Path | Content | Versions |
|---|---|---|
/Library/Logs/DiagnosticReports/ | System-wide and daemon reports | All |
~/Library/Logs/DiagnosticReports/ | Reports for the user's processes | All |
.../DiagnosticReports/Retired/ | Older reports moved aside by SubmitDiagInfo | All recent |
<process>-YYYY-MM-DD-HHMMSS.ips | JSON crash (bug_type 309) and other .ips types | 12 Monterey+ |
<process>_YYYY-MM-DD-HHMMSS_<host>.diag | Text resource and microstackshot reports (e.g. .cpu_resource.diag) | Observed on 26 Tahoe |
*.crash | Text crash reports | 11 Big Sur and earlier |
~/Library/Application Support/CrashReporter/<App>_<UUID>.plist | Per-app keys such as ForceQuitDate (plus Date, Path read by mac_apt) | Observed on 26 Tahoe |
The DiagnosticReports folders are mode 770, group _analyticsusers; admin accounts are members, so an admin can read and delete reports without sudo. Per-user folders sit inside ~/Library; collecting with a Full Disk Access terminal avoids surprises.
What it proves
- A binary at
procPathexecuted, withpid,parentProc/parentPid, and on recent releasesresponsibleProcanduserID. - When it started (
procLaunch) and when it crashed (captureTime), and how long the system had been up. - Code identity at crash time:
codeSigningID,codeSigningTeamID,codeSigningFlags, plus bundle version andslice_uuidin the header. - Loaded libraries (
usedImages), which exposes injected or unusual dylibs. - Why it died:
exception(type, signal, codes) andtermination(namespace, reason, and which process killed it). - For force-quits, the CrashReporter plist records
ForceQuitDateper application.
It does not prove that the program did anything harmful, and the absence of reports only means nothing crashed (or reports were deleted).
Key fields
.ips files hold two JSON objects: a one-line metadata header, then the report body.
| Object | Field | Meaning |
|---|---|---|
| Header | name, app_name, bundleID | Process and bundle |
| Header | bug_type | 309 crash; other values for other report types (288 stackshot, 298 observed for JetsamEvent) |
| Header | timestamp, os_version, incident_id, slice_uuid | Report time, OS build, unique ID, binary UUID |
| Body | procName, procPath, pid | Crashed executable |
| Body | parentProc, parentPid, responsibleProc, userID | Who launched it and as which user (last two observed on 26) |
| Body | procLaunch, captureTime, uptime | Launch time, crash time, seconds since boot |
| Body | codeSigningID, codeSigningTeamID, codeSigningFlags | Signing identity (observed on 26) |
| Body | exception, termination, asi | Cause, killer, app-specific messages |
| Body | usedImages, threads, faultingThread | Loaded images and backtraces |
| Body | translated, cpuType | Rosetta and architecture |
Apple redacts paths in procPath and usedImages: the user name becomes USER, volume names become VOLUME and intermediate folders collapse to * (for example /Users/USER/*/tool, observed on macOS 26), so the exact directory is often not recoverable from the report alone.
Timestamps
timestamp, procLaunch and captureTime are strings in local time with an explicit offset, e.g. 2026-09-29 10:09:30.00 +0200. File names use local time without an offset. uptime is seconds since boot. CrashReporter plist dates are plist date values (UTC).
tail -n +2 app-2026-09-29-100930.ips | jq -r '[.procLaunch, .captureTime, .procPath, .parentProc] | @tsv'
Retention
SubmitDiagInfo periodically moves older reports into Retired and cleans that folder up, so expect days to weeks of history rather than months. Users can delete their own reports, and admins can delete system reports because of the _analyticsusers group permission. Older copies may exist in APFS snapshots, Time Machine or a sysdiagnose.
Collection
sudo ditto /Library/Logs/DiagnosticReports ./case/diag_system
for u in /Users/*; do
[ -d "$u/Library/Logs/DiagnosticReports" ] && \
sudo ditto "$u/Library/Logs/DiagnosticReports" "./case/diag_$(basename "$u")"
[ -d "$u/Library/Application Support/CrashReporter" ] && \
sudo ditto "$u/Library/Application Support/CrashReporter" "./case/crashreporter_$(basename "$u")"
done
- Aftermath copies system and per-user
DiagnosticReports. - UAC collects
/Library/Logsand each~/Library/Logs(files/logs/macos.yaml). - sysdiagnose bundles recent reports.
Parsing
- jq or Python: read line 1 as the header, the rest as the body.
for f in */*.ips; do
head -1 "$f" | jq -r --arg f "$f" '[$f, .bug_type, .name, .timestamp] | @tsv'
done | sort -t$'\t' -k4
tail -n +2 suspect.ips | jq '{procPath, parentProc, responsibleProc, userID,
codeSigningID, codeSigningTeamID, procLaunch, captureTime, exception, termination}'
- mac_apt
CRASHREPORTERparses the per-user CrashReporter plists (Date,ForceQuitDate,Path). - Console on a Mac renders
.ipsin the traditional text layout.
Investigator tips
- Grep all reports for
/tmp/,/Users/Shared/and/private/var/folders/inprocPathandusedImages: legitimate apps rarely run from there. Paths under a home folder or volume are redacted (/Users/USER/*/<name>), so recover the real location from other artifacts. - An empty
codeSigningTeamID, ad-hoc flags, or aparentProcofbash,zsh,osascriptorpython3for a GUI-looking binary deserves a closer look. Pivot to launchd jobs. terminationnames the killing process (byProc) and anamespace; a code-signing termination points to a modified or badly signed binary, which ties in with Gatekeeper and XProtect.- Use
slice_uuidandusedImagesUUIDs to match a binary recovered elsewhere, even if it was renamed. - Correlate
captureTimewith the Unified Logs (ReportCrash,osanalyticshelper) for surrounding context.