Skip to main content
The macOS collector (the Hilt EDR app and its ESensor Endpoint Security extension) emits one event per security-relevant kernel action. Those events are shipped over HTTPS to the Hilt edr-collector, routed through MSK Kafka and the enrichment service (ENRICH_PLATFORM=macos), and land in a single, purpose-built ClickHouse table: endpoint_events. endpoint_events is a wide, macOS-native table typed by event_class and event_type. Per-class columns are populated only for the events that use them; everything else is left empty. There is no Linux cgroup, container, pod, or Kubernetes clutter in this schema — those concepts do not apply to an endpoint. The defining property of this table — the macOS differentiator — is that every single row carries code-signing trust and application attribution as first-class columns. A file read, a network flow, and a process exec all arrive already stamped with “what signed this binary, do we trust that signature, and which user-facing application is responsible.” On Linux, none of that exists at the kernel-event level. On macOS it rides on every row, which turns questions like “which unsigned application read ~/.ssh?” into a single WHERE clause.

Schema overview

Each row is one observed kernel event with four layers of columns: This document walks each layer in turn, then lists the event_type values.

Common header (every event)

The header identifies when, where, and who — the same actor metadata on every row regardless of event class.
wall_time_ns is the authoritative event timestamp from the Endpoint Security message. event_time is the derived DateTime64 column you filter and partition on in ClickHouse.

Code-signing identity (every event) — the macOS differentiator

On macOS, the kernel knows the signing identity of every running binary, and Apple’s Endpoint Security framework hands it to ESensor on each message. The collector promotes that identity to dedicated columns, so trust is queryable on every event — not just on exec.

The code_signature verdict

code_signature collapses Apple’s signature evaluation into one of four trust tiers: This is the column that makes macOS telemetry distinctive. Because the verdict is on every row — file, network, and process alike — you can ask trust questions about any action:
On the Linux collector this query cannot be expressed: there is no per-event notion of signing trust.

Application attribution (every event) — the macOS differentiator

A modern macOS app is not one process. Google Chrome alone spawns dozens of Google Chrome Helper, Google Chrome Helper (GPU), and Google Chrome Helper (Renderer) processes. Looking at raw comm values, the signal is scattered across helper processes that mean nothing to an analyst. The macOS collector folds every event back to the owning application using Apple’s Endpoint Security “responsible process” concept, so activity is grouped the way a human thinks about it. This means a single WHERE application_id = 'com.google.Chrome' returns the entire footprint of Chrome — every helper exec, every file it touched, every flow it opened — without enumerating helper names. session_id further narrows that to one specific launch of the app, and responsible_pid lets you pivot from any event to the accountable process.
responsible_pid and application_id are how the dashboard’s Investigate, Files, Networks, and Users views attribute scattered helper-process activity to the application a user actually ran. The folding happens at enrichment time so it is consistent across every query.

Per-event payloads

Beyond the common header and the two always-present identity layers, each event class carries its own payload columns. The long tail of less-common attributes lands in an attrs map.

Process payload — exec, fork, signal

exec is the spine of the process model: it carries the argv, the signing identity, the team id, and the cdhash all on one row. signal events record kill attempts — attrs['target_pid'] and attrs['signum'] reveal who tried to terminate whom, which surfaces both attacker kill-chains and attempts to tamper with the collector itself. file_open dominates event volume (~95%+), which is why ESensor applies aggressive userspace filtering before anything leaves the host — see Agent filtering. The xattr_* events are macOS-specific and high-signal: they capture changes to com.apple.quarantine, the extended attribute Gatekeeper uses to mark downloaded files. An xattr_delete on a quarantine attribute is a classic Gatekeeper bypass — stripping the “downloaded from the internet” flag so the OS will run a file without prompting.

Network payload — net_flow

Network flows come from a combination of an lsof/socket poller and the NetFilter NetworkExtension content-filter system extension, which resolves each flow’s audit token back to the responsible app. Because of NetFilter, a net_flow row already knows which application opened the connection — bundle_id answers “what made this connection” without a separate process-to-socket correlation step.
net_flow records connection metadata only — destination, ports, byte counts, and the responsible app. It does not capture packet payloads, and by default it does not resolve DNS names.

Persistence payload — btm_add

btm_add events come from macOS 13+ Background Task Management (BTM) and fire whenever a launch agent, launch daemon, or login item is registered — i.e. when something installs itself to persist across reboots. This is the single highest-signal persistence event on macOS: it is how the vast majority of macOS malware (and legitimate auto-start software) survives a restart.

Device payload — mount

mount events fire when a filesystem is mounted — most interestingly removable media (USB drives) and disk images (DMGs), both common vectors for data exfiltration and software delivery.

Event types

The collector subscribes to 12 Apple Endpoint Security events plus a network source, and emits the following event_type values into endpoint_events:
xattr_delete and mount are rare by nature (quarantine removal and USB/DMG mounts) — they are subscribed and emitted, but a quiet host may show none over a short window. signal, file_unlink, and file_rename are subscribed as AUTH events so ESensor can also deny tampering with itself, but they still emit equivalent telemetry rows.

How identity and attribution are filled

The identity and attribution layers are not best-effort metadata — they are populated at high fill rates and are the columns most queries pivot on. Verified fill rates from live data: For more on how telemetry travels from ESensor to ClickHouse, see End-to-end data flow. For how raw event volume is reduced before it leaves the host, see Agent filtering.

What the collector does not capture

Consistent with the Linux collector’s design philosophy, the macOS collector observes system activity at the metadata level, with one documented exception — the clipboard (below). It does not capture:
  • File contents — only the path, operation type, flags, and (for renames) the destination
  • Packet payloads — only the flow’s destination, ports, byte counts, and responsible app
  • DNS query contents — net_flow does not resolve domain names by default
  • Keystrokes — paste detection is a listen-only Cmd+V tap; no key content is recorded
  • Screen content — Screen Recording is never requested
  • Memory regions or process memory
  • Environment variables
  • Credentials or any user data beyond what standard tools like ps, lsof, or codesign would expose — except clipboard content, below
Exception — clipboard content. The clipboard sensor is on by default and by default stores the copied text itself, which will include credentials and personal data that users copy. It can be reduced to metadata + SHA-256 + on-device classification, or disabled outright, by managed preference. See Clipboard and data movement. In other words, ESensor reports that a binary opened a file, signed by whom, on behalf of which app — never what was in the file. All event shipping is over outbound HTTPS only to the configured ingest endpoint; the collector opens no inbound sockets and makes no phone-home connections.
Last modified on October 8, 2026