Ask the Endpoint: osquery as Huntbase's Truth Layer
Logs record what a system chose to report. osquery answers what the machine looks like right now. How Huntbase turns live endpoint truth into a core layer of every hunt.
Logs tell you what a system chose to report. osquery tells you what the machine looks like right now. Huntbase makes that live view a core part of the hunt.
The log is a record. The endpoint is the fact.
Most threat hunting is archaeology. You query a lake of logs — a record of whatever some agent was configured to emit months ago, by someone who has since changed teams. If an event wasn't on that list, it isn't in the lake, and no clever query will conjure it.
Attackers know this. The gap between what an endpoint does and what it reports is where persistence lives: a scheduled task nobody logged, a driver loaded before the collector started, a browser extension that arrived through a sync profile.
osquery inverts the question. Instead of waiting for the endpoint to report, you ask it directly, in SQL. The running machine — its processes, open sockets, registry, startup items, and installed packages — becomes a database you can query at hunt time.
Huntbase treats this as a core layer, not a side channel. When a hypothesis needs ground truth, we ask the endpoint.
One dialect, three operating systems, one catalog
osquery also flattens a hard heterogeneity problem. macOS, Windows, and Linux expose very different internals; osquery presents them all as tables. processes and process_open_sockets mean the same thing everywhere, while platform-specific tables like shimcache (Windows), launchd (macOS), and crontab (Linux) reach into each OS's internals. One query language, one mental model, three platforms.
The catch: nobody has memorised those tables. Huntbase ships an annotated catalog of over 100 osquery table definitions, each describing what the table and every column mean. We index that catalog for semantic search instead of parking it in a documentation site — a choice that pays off once an agent writes the queries. More on that below.
Live questions, not standing collection
There's a common way to use osquery badly: schedule every interesting table on every endpoint, ship the results into a data lake, and hunt the exhaust. You pay for storage, pay for egress, wait for the collection interval, and end up hunting a stale copy of the truth.
Huntbase asks endpoints questions on demand. A hypothesis becomes a query with a bounded lifetime, dispatched through Huntbase Endpoint Control to the endpoints that can answer it. The endpoint computes the results the moment you ask, so they are never stale.
Targeting is explicit and layered. A hunt can target a platform, a hostname, a specific device, or — most useful in practice — a Huntbase endpoint tag, so "all finance laptops" or "everything in the DMZ" is a first-class target rather than a spreadsheet exercise. With no target specified, the query broadcasts across the environment.
Query templates also declare which platforms they're valid on, and dispatch intersects the target set against that declaration before anything leaves the building. A Windows-only persistence check never reaches your macOS fleet, so nobody wades through a wall of empty results. We normalise platform names on the way in too: analysts type macos, osquery says darwin, and neither should have to care.
Figure 1 — One question, targeted to the endpoints it makes sense for; answers stream back and land as entities, not just rows.
Every row already knows where it came from
A raw osquery result row is anonymous. It tells you a process was running — not which machine ran it, on what OS build, on which network, or with whom logged in. The obvious fix, joining every result back to an inventory table at query time, is slow, brittle, and wrong the moment inventory drifts.
So we don't join. Huntbase uses osquery's decorator mechanism to stamp every result row with host context at the source — which machine answered, what it was running, where it sat on the network, and who was logged in at the time. Each row arrives self-describing.
The same mechanism gives us binary drift for free. The decorators record the agent binary's hash at load time and its current on-disk hash; when the two disagree, every row that agent produces is flagged at ingest — without anyone writing a detection for it.
Context travels with the data instead of being reconstructed after the fact. Six months later, when someone questions a finding, the row still records exactly which machine, in which state, produced it.
Rows become entities, not just results
Most platforms stop at a table of results. That's also where the value stops, because a human has to read a table.
Huntbase maps osquery result rows into OCSF 1.7 entities and relationships. An asset query becomes a device that runs an operating system. A network query becomes a device that connected to an IP address. A software inventory query becomes a device that has a product. These land in the entity graph alongside everything else Huntbase knows about your environment, from cloud posture to threat intelligence. Dozens of tables carry generated mappings on top of the hand-authored ones, so coverage extends well past the tables anyone would think to configure.
This creates a useful side effect. An analyst runs a routine "what software is installed on these hosts" query as one step of an unrelated hunt. Those rows extract into product entities, and a standing vulnerable-endpoint query that was missing inventory now lights up.
Hunting produces coverage as a byproduct. You look for one thing and leave the environment better mapped than you found it.
Figure 2 — Two pipelines observe the same machine; one identity authority makes them the same machine.
One host, one node
Huntbase learns about an endpoint in two separate ways: it checks in through Endpoint Control, and it answers queries. Two pipelines, two schedules, two payload shapes. In many systems, that's how the same laptop ends up represented three times under slightly different names — a graph that quietly lies to you.
Both pipelines derive entity identity through the same authority — one shared derivation, not two implementations that are supposed to agree. A check-in and a query result about the same machine converge on the same device node, OS node, and agent node. Each endpoint has exactly one representation, whichever pipeline observed it.
That's what earns the phrase "truth layer". A truth layer where the same host appears twice isn't one.
Teaching an agent to speak osquery
Huntbase's agent, Scout, writes these queries. Three disciplines make that work.
Discovery over dumping. Handing a model the full catalog of table schemas fails twice: it burns the context budget and buries the relevant table in noise. Scout searches the annotated catalog semantically and pulls only the tables a question needs.
Dialect discipline. osquery is SQLite. It looks enough like SQL that a model trained on the internet constantly reaches for PostgreSQL constructs that don't exist here. Scout sticks to the portable subset — time bounds go through the epoch column (WHERE time >= strftime('%s','now','-7 days')) rather than INTERVAL arithmetic — and point-in-time inventory tables get no time filter at all, because there a timestamp predicate silently returns nothing.
Grounding. Two gates stand between a generated query and an endpoint. Huntbase re-derives the query language from the curated catalog rather than trusting the model, which will confidently volunteer dialects that don't exist. And it drops any query that references a table missing from the resolved schema. A hallucinated table name never runs.
Figure 3 — A generated query has to survive grounding and dialect checks before an endpoint ever sees it.
"No results" is not "clean"
An empty result set is ambiguous. It might mean the technique isn't present in your environment. It might mean half the fleet was asleep in an airport lounge.
Huntbase tracks two independent facts for every endpoint in a run: whether it was targeted, and whether it responded. An empty result with full response coverage is evidence of absence. The same empty result with sixty percent coverage is still an open question.
Coverage is part of the answer, not metadata about it. That distinction separates a hunt that concludes from one that merely stops.
Ask the machine
osquery isn't bolted onto the side of Huntbase. It lets a hunt stop inferring from logs and ask the machine directly, get an answer stamped with its own provenance, merge it with everything else we know about that host, and leave the environment better mapped than before.
The fastest way to judge any of this: point it at your own fleet and ask something hard.