curl + openssl over POSIX sh, with no
Python runtime or third-party packages on the endpoint. It plants the bait, then
watches the bait paths for a read and fires a signed callback the moment one
happens.
Sensors
fs_usage is the real sensor: it yields genuine open/read events and, via ps,
the process and user that read the file - which enrich the alert. It requires
root, which the agent has when run under MDM. The firehose is trimmed at the
source by grep-ing to only the bait paths, and noise processes (Spotlight,
mds, the agent itself, …) are filtered out. The atime fallback exists so
non-macOS hosts get some coverage, but it’s strictly best-effort.
The agent protocol
The agent never parses JSON. The agent-facing API speaks a plain-text protocol so enroll, pull, and the signed callback are each a few lines of shell:- Enroll -
POST /api/enrollwith the shared enroll token; the response iskey=valuelines, including the endpoint’sagent_token. - Pull -
GET /api/agent/deploymentsreturns this endpoint’s own instances as tab-separated records (deployment id, path, HMAC secret, and URLs for the bait content and the callback). The bait content isn’t inlined - it can be multi-line - so the agent fetches it raw from the per-deployment content URL. - Trigger - on a read, the agent builds a
key=valuebody (deployment_id,event_type,process,pid,os_user,accessed_path,triggered_by,timestamp) and POSTs it toPOST /api/trigger.
openssl dgst -sha256 -hmac over the exact request body and sends it as
X-Thumper-Signature: sha256=<hmac>. If the server stops recognizing the
deployment (a DB reset or redeploy returns 401), the agent re-enrolls,
re-pulls, and resends - so the read that triggered it still alerts under fresh
credentials. See the security model for how the server
verifies it.