Collect QuarantineEventsV2: UAC, Aftermath, Velociraptor
How to collect macOS QuarantineEventsV2, its -wal and -journal files, quarantine xattrs and .LastGKReject by hand or with UAC, Aftermath and Velociraptor.
TL;DR. On a live Mac, the fastest collection is three commands from a Terminal with Full Disk Access: copy ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2* (the * brings the -wal and -journal files), dump quarantine attributes with xattr -r -l -x, and grab .LastGKReject if it exists. UAC, Aftermath and Velociraptor all collect the database; none of them collects quarantine attribute values, so add the xattr listing yourself. Hash first, work on copies.
What to collect
A complete quarantine collection has three parts:
- The database of every user: QuarantineEventsV2 plus its
-waland-journalcompanions. The companions can hold recent committed changes and older page copies, which is where deleted records survive (see recovering deleted records). - The attribute values of files in the folders you care about:
com.apple.quarantineandkMDItemWhereFroms. They carry the UUID that joins a file to its database row. .LastGKReject, Gatekeeper's record of the last item it refused. It may not exist, or may exist and be empty.
The easiest way: copy by hand on a live Mac
Open Terminal, make sure it has Full Disk Access, and run the commands below. Add sudo when you need to read other users' folders.
Current user
mkdir -p ~/qcase
cp -p ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2* ~/qcase/
xattr -r -l -x ~/Downloads ~/Desktop ~/Documents ~/Library/LaunchAgents > ~/qcase/xattr_$(id -un).txt 2>/dev/null
cp -p preserves timestamps and modes; the trailing * copies the database together with any -wal or -journal file. The xattr -r -l -x listing records every extended attribute as a hex dump, which keeps the exact bytes. ~/Library/LaunchAgents is in the list on purpose: a downloaded file sitting in an autostart folder is one of the leads worth checking.
All users
Run as root to copy every user's database into its own folder:
for u in /Users/*; do
f="$u/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2"
[ -f "$f" ] || continue
d="$HOME/qcase/$(basename "$u")"
sudo mkdir -p "$d" && sudo cp -p "$f"* "$d/"
done
Repeat the xattr listing for each user whose folders matter.
Gatekeeper's last rejection
The .LastGKReject file has lived at two paths in Apple's sources, so try both:
for f in /private/var/db/.LastGKReject /private/var/db/SystemPolicyConfiguration/.LastGKReject; do
[ -f "$f" ] && sudo cp -p "$f" ~/qcase/"$(basename "$(dirname "$f")")_LastGKReject"
done
Only the last rejection is kept, and the file may be missing. It can also exist without any rejection in it: on one live macOS 26.6 system, /private/var/db/.LastGKReject was absent and /private/var/db/SystemPolicyConfiguration/.LastGKReject was a small XML property list holding an empty dictionary. Quarantine Parser reports that case as "no rejection recorded". What the file contains is covered in .LastGKReject as Gatekeeper evidence.
UAC
UAC (Unix-like Artifacts Collector, github.com/tclahr/uac) has an artifact files/system/quarantine_events.yaml that collects %user_home%/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2. The ir_triage and full profiles include it, because they include files/system/*.
sudo ./uac -p ir_triage /tmp
sudo ./uac -a ./artifacts/files/system/quarantine_events.yaml /tmp
The first command runs the whole triage profile, the second only this artifact. Output is uac-<hostname>-macos-<timestamp>.tar.gz by default (-f zip for a ZIP). UAC does not collect xattr values, so run the xattr -r -l -x command above as well.
Aftermath
Aftermath (Jamf, github.com/jamf/aftermath) runs with:
sudo ./aftermath
Output goes to /tmp by default; -o chooses another location. Aftermath copies each user's database to Artifacts/raw/lsquarantine_<username>, without the -wal. Its file metadata lists xattr names and kMDItemWhereFroms, not quarantine values. Again, add an xattr listing if the attribute values matter.
Velociraptor
Two approaches, depending on what you need:
- Parsed on the endpoint. The
MacOS.System.QuarantineEventsartifact queries the database on the endpoint and returns the columns DownloadTime, DownloadURL, Origin, AgentName, AgentBundle, User and EventUUID. Its default glob is/Users/*/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2. This is quick, but you only get what the query returns: no free space, no companions. - Raw files. Use
Generic.Collectors.Filewith Root/and a Glob such asUsers/*/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2*. The trailing*brings the companions, and you keep the free space that recovery needs.
If you deal with ZIPs made by Finder, MacOS.Forensics.AppleDoubleZip reads the __MACOSX AppleDouble entries they contain.
mac_apt and Plaso
mac_apt's QUARANTINE plugin parses both the database and .LastGKReject. Against a mounted image:
python mac_apt.py -o out MOUNTED /Volumes/evidence QUARANTINE
Against a single file:
python mac_apt_artifact_only.py -i com.apple.LaunchServices.QuarantineEventsV2 -o out QUARANTINE
Plaso also has an ls_quarantine SQLite plugin, useful when the database goes into a broader super-timeline.
Gotchas
Full Disk Access and TCC
macOS privacy protections (TCC) can stop Terminal from reading user folders. Grant Full Disk Access to the Terminal you use before collecting; otherwise errors are easy to miss, especially with 2>/dev/null hiding them. Check that the copied files are not empty.
WAL and journal companions
A database copied without its -wal can miss committed changes that have not been checkpointed into the main file yet, and you lose the older page copies too. On the macOS 26.6 system observed, the database used rollback-journal mode, so a -journal file is the more likely companion. Collect whatever is there.
AppleDouble on exFAT
If files were copied to exFAT, FAT or SMB volumes, macOS stores their extended attributes in AppleDouble ._name files. Collect those ._ files too: they can hold the quarantine value and WhereFroms of a file that left the Mac.
Hash first
Hash the collected files before any analysis and work on copies. Opening a database with sqlite3 can modify it (see recovering deleted records).
Extended attributes lost in transit
Extended attributes do not survive every trip. Copying to media without xattr support, or with tools that drop them, loses the values. The xattr -r -l -x text listing is the safest carrier: it is a plain file and survives any transport.
Loading the collection
Quarantine Parser accepts the UAC .tar.gz, the Aftermath archive or folder, and Velociraptor collection ZIPs as they are, as well as parsed MacOS.System.QuarantineEvents results in JSON lines and your own ~/qcase folder. Everything runs in the browser. The home page also has a copy-ready guide, How to get your data. For the meaning of what you collected, start with QuarantineEventsV2 forensics and com.apple.quarantine flags; a quick reference is on macforensics.app.
Frequently asked questions
Does the Terminal need Full Disk Access to copy QuarantineEventsV2?
Run the copy from a Terminal that has Full Disk Access, and add sudo for other users' folders. Without it, macOS privacy protections (TCC) can block reads in user folders and leave you with an incomplete collection.
Does UAC collect quarantine attributes?
No. UAC's quarantine_events artifact copies the QuarantineEventsV2 database, but UAC does not collect xattr values. Capture com.apple.quarantine values separately with xattr -r -l -x on the folders that matter.
Why copy the -wal and -journal files too?
They can hold changes that are not yet in the main file and older copies of pages, which is where deleted records survive. The trailing asterisk in the cp command copies them together with the database.
Can Quarantine Parser read a UAC or Velociraptor collection directly?
Yes. Drop the UAC .tar.gz, the Aftermath archive or folder, or a Velociraptor collection ZIP as it is. Everything is processed in your browser and nothing is uploaded.