Threat Intelligence

Osquery Tables Explained: The 25 Most Useful Tables

More than 270 tables, 25 that matter. The identity, activity, software, persistence, and event tables that answer real security questions, with the joins to use.

Alex Gibson, Co-Founder and Principal at Artemes AI
Alex Gibson
Co-Founder, Principal
Jul 19, 2026 10 min read
Abstract visualization of osquery tables organized in layers across an endpoint fleet

Osquery ships more than 270 tables. Teams that get real value from the agent live in about 25 of them.

The rest of the schema is not waste, it is coverage for questions you will ask twice a year. But when teams stall on osquery, the cause is almost always the same: they browse osquery tables alphabetically like a phone book instead of learning the two dozen that answer daily security questions. This guide covers those tables, grouped by the question each one answers, with the joins that make them useful. If you are still deciding whether the agent belongs in your stack, start with what osquery is and the full osquery handbook.

Infographic

Osquery tables, organized by the question they answer

More than 270 tables collapse into five working layers. Learn the layer, and the table names take care of themselves.

Five layers of osquery tables grouped by security questionA layered diagram with five horizontal bands. Layer one, identity: system_info, os_version, users, interface_addresses. Layer two, activity: processes, listening_ports, process_open_sockets, logged_in_users. Layer three, software: programs, deb_packages, rpm_packages, apps, chrome_extensions. Layer four, persistence: crontab, services, launchd, scheduled_tasks, startup_items, authorized_keys. Layer five, history: process_events, socket_events, file_events, which record changes over time instead of current state.One agent, five questions1 · What is this machine?system_info · os_version · uptime · interface_addresses · users2 · What is it doing right now?processes · listening_ports · process_open_sockets · logged_in_users3 · What is installed on it?programs · deb_packages · rpm_packages · apps · chrome_extensions4 · What survives a reboot?crontab · services · launchd · scheduled_tasks · startup_items · authorized_keys5 · What changed while you were not looking?process_events · socket_events · file_events (evented, not point in time)

How do osquery tables actually work?

There is no database sitting on the endpoint. Every table is virtual. When you run a query, osquery calls operating system APIs at that moment, builds rows in memory, hands them to the embedded SQLite engine, and throws them away when the query finishes. The official SQL introduction describes the mechanics. The practical consequence: results are as fresh as the moment you asked, and a table you never query costs you nothing.

Coverage varies by platform. Some tables exist everywhere (processes, users, listening_ports). Others are specific to one operating system, like the Windows registry table or the macOS launchd table. The schema browser at osquery.io filters by platform and version, and it is the reference worth bookmarking. The set still grows: the 5.19 release in August 2025 added an entitlements column to the macOS signature table and taught vscode_extensions to see VS Code forks, per the project changelog.

Which tables identify the machine?

Five tables give you an asset inventory that is always current. system_info returns hardware model, CPU, and memory. os_version returns platform and build, the column your vulnerability matching depends on. uptime tells you how long since the last reboot, which is how you find the server that has quietly skipped six months of kernel patches. interface_addresses maps the machine to the network. users enumerates local accounts, including the ones your identity provider does not know about.

This layer sounds boring until you price the alternative. A fleet of 2,000 hosts inventoried by a quarterly spreadsheet exercise at three minutes per host is 100 hours of labor, four times a year, and the data is stale the week it ships. One scheduled query replaces all 400 of those hours with rows that update daily.

Which tables show what is running right now?

The activity layer is where investigations start, and three tables carry most of the load.

processes is the single most queried table in the schema: pid, name, path, command line, parent pid, and the on_disk column that flags a binary deleted after launch, a favorite attacker trick. listening_ports shows every bound socket. process_open_sockets shows active connections with remote addresses. logged_in_users tells you who is on the box while the weird process runs.

The join every team should know maps exposed ports to the programs behind them:

SELECT p.name, p.path, lp.port, lp.address
FROM listening_ports lp
JOIN processes p USING (pid)
WHERE lp.address = '0.0.0.0';

Run that across a fleet and you have an exposure map that no network scanner can match, because it comes from inside the host and names the process, not just the port. The Verizon 2026 DBIR put vulnerability exploitation at 31 percent of initial access, up from 20 percent the prior year and now the top vector. Knowing which vulnerable service actually listens on an external interface is the difference between patching what matters and patching alphabetically.

Which tables inventory installed software?

Software inventory is fragmented by design, one table per packaging system. programs covers installed Windows software. deb_packages and rpm_packages cover Debian and Red Hat family Linux. apps reads macOS application bundles with versions and signatures. chrome_extensions and vscode_extensions cover the two ecosystems where supply chain problems keep showing up, and both include the permissions each extension holds.

Version columns in these tables are the raw material for vulnerability matching. They are also where naive matching goes wrong, because a package being present says nothing about whether it is loaded, reachable, or exposed. We wrote about that failure mode in why CVE scanners fly blind, and about what the package tables can and cannot do in osquery vulnerability detection. The fix is not a better package list. It is joining the package list against the activity layer above before calling anything urgent.

Which tables catch persistence?

Attackers who survive a reboot did so through a mechanism your operating system will happily enumerate. crontab lists scheduled jobs on Linux and macOS. services and scheduled_tasks cover the Windows equivalents. launchd covers macOS daemons and agents. startup_items spans login and startup hooks. authorized_keys lists every SSH key with access to every local account, a table worth a scheduled query on its own. etc_hosts catches DNS redirection that never touches a resolver log.

None of these tables is interesting once. All of them are interesting as diffs. A new row in crontab on a production host is either a change ticket or an incident, and there is rarely a third option. This is why persistence tables belong in a scheduled daemon config rather than ad hoc shell sessions, a distinction we cover in the osqueryi vs osqueryd comparison.

What are evented tables and when do you need them?

Everything above reports state at the moment you ask. A process that runs for two seconds between queries is invisible. Evented tables close that gap: osquery subscribes to operating system event streams, buffers what happens, and serves the backlog when the scheduled query next runs. process_events records every execution with command line and hash. socket_events records connections as they open. file_events watches paths you designate for integrity monitoring, using inotify on Linux and FSEvents on macOS, with ntfs_journal_events as the Windows counterpart, per the FIM documentation.

Evented tables cost more. They require enabling event subsystems (audit or eBPF on Linux, EndpointSecurity on macOS), they buffer to disk, and a busy build server can generate tens of thousands of rows an hour. The process auditing guide documents the flags. Start with point in time tables, prove you can act on what they show, then add events where the detection case justifies the volume.

Which platform specific tables are worth learning?

The shared tables cover the daily questions, but each operating system contributes tables that have no equivalent elsewhere, and a few of them earn permanent spots in a schedule.

On Windows, the registry table turns the entire registry into queryable rows, which means Run keys, IFEO debugger hijacks, and disabled security settings all fall to a WHERE clause on a key path. The services table includes the binary path and start type for every service, and certificates enumerates trusted roots, the table that catches a rogue CA certificate installed to make interception look legitimate. The wmi_cli_event family covers WMI persistence, a technique that stays popular precisely because so few tools look at it.

macOS brings its own set. launchd is the persistence table, but the signature table deserves attention too: it reports code signing status for binaries, and since the 5.19 release it includes entitlements, so you can find software that holds sensitive capabilities like camera or full disk access. On Linux, the kernel_modules table shows loaded modules (rootkits have to live somewhere), and the sudoers table exposes exactly who can escalate, which auditors ask about every single year.

The pattern worth internalizing: whenever a platform has a mechanism attackers use, osquery usually has a table watching it. Before writing a custom collector or buying another tool, spend five minutes in the schema browser. The table you want probably shipped years ago.

The tables that watch osquery itself

Three meta tables keep the agent honest. osquery_info reports version and uptime for the agent, which is how you find hosts running a build with known agent vulnerabilities (the 5.23.1 release in June 2026 patched heap overflows in two Windows tables, so this is not hypothetical). osquery_schedule reports executions, wall time, and output size per scheduled query, your first stop when the watchdog starts killing a worker. osquery_events shows which event publishers are active, the fastest way to learn your evented config is not actually collecting anything.

How should you explore tables on a live host?

Reading schema documentation teaches you column names. It does not teach you what your environment looks like, and that second kind of knowledge is what makes query results readable later. The fastest way to build it is twenty minutes in the interactive shell on one representative host per platform:

.tables
.schema listening_ports
SELECT COUNT(*) FROM processes;
SELECT name, path FROM processes LIMIT 10;

Ask each of the five layer questions against a machine you understand, and check whether the rows match what you expected. When they do not, you have learned something about the host or about the table, and both lessons are cheap now and expensive during an incident. A team of four spending one afternoon this way banks roughly 16 hours of learning that pays back the first time someone has to read fleet results at speed.

Two cautions from the field. First, column names are consistent within a table but not across platforms: the same logical fact can live in differently shaped tables on Windows and Linux, so fleet queries need a platform discriminator or separate scheduled entries per platform. Second, a handful of tables (file, hash, and friends) require a WHERE constraint before they return anything at all, by design, because unbounded filesystem walks are not a reasonable thing to ask of a production host. Both behaviors are covered in depth in our guide to writing osquery queries.

Frequently asked questions

How many tables does osquery have?

More than 270 across Windows, Linux, and macOS, with the exact count depending on version and platform. The schema browser at osquery.io shows the current set per release. No single platform sees all of them.

Can I list osquery tables from inside the shell?

Yes. In osqueryi, .tables lists every table available on that host and .schema processes prints column names and types for a specific table.

Do unqueried tables slow the endpoint down?

No. Tables are virtual and generate rows only when queried. Cost comes from what you schedule and how often, plus event subsystems if you enable them. The watchdog restarts the worker if a query misbehaves.

Can I add my own osquery tables?

Yes, through extensions, or through ATC (auto table construction), which maps any SQLite database already on the host, like browser history, into a queryable table with a config entry.

The takeaway

Do not study the schema. Pick the five questions in the infographic, open osqueryi on one representative host, and answer each question with one or two tables from this list. That is 25 tables, learned in an afternoon, and it covers most of what incident responders and vulnerability teams ask of an endpoint. Then schedule the queries worth repeating. Collecting the rows is the easy half; deciding which rows matter is where the time goes, and that judgment layer, deep endpoint context read by an AI engine, is exactly what Artemes AI builds.

Artemes AI

See which of your findings actually matter

Artemes AI combines deep endpoint context with AI-driven analysis to show which findings are actually exploitable on your hosts—not just everything a scanner can list. We are onboarding early access teams now.

Alex Gibson, Co-Founder and Principal at Artemes AI

Alex Gibson

Co-Founder, Principal

Alex writes about configuration drift, operational security evidence, endpoint telemetry, AI-assisted triage, and the practical work of turning signals into better remediation decisions.

Osquery
Endpoint Telemetry
Blue Team
Found this useful? Share it.