Skip to content

QuarantineEventsV2 · xattr · AppleDouble · .LastGKReject

Where did this file come from?

Drop a Mac's QuarantineEventsV2 database, xattr listings, AppleDouble files or .LastGKReject. Get one download timeline with decoded quarantine flags, rows recovered from free space, and leads worth a second look. Parsed in your browser with WebAssembly: nothing is uploaded.

Drop a Mac collection, a QuarantineEventsV2 database or xattr output

QuarantineEventsV2 (+ -wal / -journal), xattr -l / -r -l -x listings, AppleDouble ._ files, .LastGKReject, or a whole folder, ZIP or UAC tar.gz. Several users at once.

The sample is synthetic: a fictional finance laptop, FIN-MBP-03, on 14 September 2026.

Parsed in your browser — nothing is uploaded

How to get your data

Full collection guide

Download provenance lives in each user's QuarantineEventsV2 database and in extended attributes on the files themselves. Collect both: the database proves the download, the attributes tie it to files on disk.

  1. Copy with Terminal, or collect with UAC, Aftermath or Velociraptor
  2. Drop the folder, ZIP or tar.gz here
  3. Parsed locally — nothing leaves the browser

On the Mac, give Terminal Full Disk Access (System Settings › Privacy & Security), then paste this block. It copies your database with its -wal/-journal files, lists quarantine and WhereFroms attributes in Downloads, Desktop, Documents and LaunchAgents as exact hex dumps, and copies .LastGKReject when present.

Terminal · zsh / bash
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
for f in /private/var/db/.LastGKReject /private/var/db/SystemPolicyConfiguration/.LastGKReject; do
  [ -f "$f" ] && cp -p "$f" ~/qcase/"$(basename "$(dirname "$f")")_LastGKReject"
done

Everything lands in ~/qcase. Drop that folder on the page.

Every account on the Mac (admin password, Terminal with Full Disk Access): databases under qcase/Users/<name>, one listing for all home folders plus the system LaunchAgents and LaunchDaemons.

Terminal · admin
for u in /Users/*; do
  f="$u/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2"
  sudo test -f "$f" || continue
  d=~/qcase/Users/"$(basename "$u")"
  mkdir -p "$d" && sudo sh -c 'cp -p "$1"* "$2/"' _ "$f" "$d"
done
sudo sh -c 'xattr -r -l -x /Users/*/Downloads /Users/*/Desktop /Users/*/Documents /Users/*/Library/LaunchAgents /Library/LaunchAgents /Library/LaunchDaemons 2>/dev/null' > ~/qcase/xattr_all_users.txt
sudo chown -R "$(id -un)" ~/qcase

Gotchas

  • Without Full Disk Access, copies from Terminal can fail with “Operation not permitted” (Desktop, Documents, Downloads and parts of ~/Library are protected by TCC).
  • Never open the original database with sqlite3 or a GUI: it may checkpoint the WAL or rewrite pages and destroy deleted records. Hash, copy, then analyse the copy.
  • zip and cp to non-Mac media drop extended attributes; keep the xattr listing or use ditto if you need the attributes themselves.
  • Times are UTC: the database uses Mac absolute time, the attribute hexadecimal Unix seconds; both are converted for you.

What is QuarantineEventsV2?

When an app that opts in to file quarantine (Safari, Chrome, Mail, Messages, AirDrop, sandboxed apps) writes a downloaded file, macOS attaches the com.apple.quarantine extended attribute to it and Launch Services adds a row to the user's QuarantineEventsV2 SQLite database: time, downloading app, data URL, origin page, sender for mail.

The attribute travels with the file; the database row usually stays after the file is deleted. The UUID at the end of the attribute joins the two. Together they answer the first question of many Mac investigations: where did this file come from, when, and was it opened?

What this tool reads

  • ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2 (table LSQuarantineEvent), with its -wal (committed frames applied, checksums verified) and -journal companions; Aftermath's lsquarantine_<user> copies; several users at once.
  • com.apple.quarantine values from xattr -p, xattr -l, xattr -r -l and xattr -r -l -x output, pasted or as text files; kMDItemWhereFroms values in the same listings.
  • AppleDouble ._ files (exFAT, FAT, SMB volumes and __MACOSX folders of Finder ZIPs), which keep a copy of the attributes.
  • .LastGKReject (last Gatekeeper rejection: time, target path from its bookmark, XProtectMalwareType) and Velociraptor MacOS.System.QuarantineEvents results.
  • Folders, ZIPs and tar.gz collections such as UAC archives, Aftermath output and Velociraptor collection ZIPs.

What it answers

  • Which apps downloaded what, from which URL and page, and when — as one timeline, per agent and per domain.
  • Which files on disk belong to which download (UUID join), including every file extracted from a quarantined archive.
  • Which items the user approved through Gatekeeper (flag 0x0040), and which item Gatekeeper refused last.
  • Whether rows were deleted: records still present in free space, freelist pages, older WAL frames or the rollback journal are recovered and marked.
  • Leads worth a look: archives, disk images, installers and scripts from rarely seen domains, file-sharing and paste hosts, downloaded files in LaunchAgents folders, WhereFroms without quarantine.

Limits

  • The database does not store the local file name; only the xattr UUID ties a file to its row. Downloads made with curl, wget, scp or git leave no quarantine trace at all.
  • Apple does not document the flag bits. Names come from open-source declarations (WebKit, Apple's Security and copyfile code); unknown bits are shown as unknown.
  • Rows without URLs and attribute UUIDs with no row are common on recent macOS releases and are not suspicious by themselves.
  • Recovery of deleted rows depends on SQLite settings and later writes: finding none proves nothing. Recovered rows can be partial.
  • Findings are leads for an analyst, not verdicts. Timestamps are shown in UTC or your browser's time zone.

How to collect

  • Quickest: the Terminal block above (Full Disk Access) copies the database with its -wal/-journal files, lists quarantine attributes with xattr -r -l -x and copies .LastGKReject.
  • UAC: artifact files/system/quarantine_events.yaml, included in the ir_triage and full profiles. Aftermath: raw copies in Artifacts/raw/lsquarantine_<user>. Velociraptor: MacOS.System.QuarantineEvents, or Generic.Collectors.File for the raw files.
  • Hash the files first and work on copies; never open the original database with sqlite3, which may change it.

FAQ

Are my files uploaded?

No. The parser is Rust compiled to WebAssembly and runs in a Web Worker in your browser. Databases, listings and archives never leave your machine; closing the tab forgets them.

Where is the QuarantineEventsV2 database?

In each user's ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2. Copy it together with any -wal and -journal file next to it, from a Terminal that has Full Disk Access, or collect it with UAC, Aftermath or Velociraptor.

How do I link a file to its download record?

Read its com.apple.quarantine attribute (xattr -p com.apple.quarantine file). The last field is a UUID; the matching LSQuarantineEventIdentifier row holds the URL, origin page and agent. Drop both the database and an xattr listing here and the join is done for you.

What does quarantine flag 0083 or 00c3 mean?

The first field is a hexadecimal bit field that Apple does not document. 0x0001 is usually read as a download, 0x0002 as written by a sandboxed app, 0x0080 as translocation and 0x0040 as approved by the user through Gatekeeper, so 00c3 is 0083 plus approval. Confirm on a system of the same macOS version before relying on it.

Can deleted quarantine events be recovered?

Sometimes. When a row is deleted, SQLite usually leaves its bytes in free space until they are reused. The tool carves those records, plus older copies in the WAL or the rollback journal, and marks them as recovered. Finding none proves nothing.