---
title: "Linux Telemetry Schema - Workshop Docs"
description: "Linux Telemetry Schema - Enterprise control plane for Santa. Manage rules, approvals, telemetry, and policies across your macOS fleet."
doc_version: "1"
last_updated: "2026-09-11"
canonical: "https://northpole.security/docs/workshop/linux"
---
# Linux Telemetry Schema

This page documents the complete schema for all telemetry event types collected by Workshop from Santa agents on Linux.

Each event type below is also the table name in SQL queries, prefixed with `linux_`: exec fields live in `linux_exec_2026`, `linux_exec_202603`, or `linux_exec_20260315` (see [table naming](https://northpole.security/docs/workshop/telemetry#table-naming-convention)). The prefix exists because `fork` and `exit` are collected on macOS too, with entirely different columns. Columns drift across Santa versions, so `DESCRIBE linux_exec_20260315` on your own data is the authoritative list.

Linux telemetry is not shared with the [macOS schema](https://northpole.security/docs/workshop/telemetry/schema/macos), including the base fields. A telemetry field with the same name on both platforms does not necessarily mean the same thing, and a query written against one platform will not run against the other. Package inventory is the exception: its platform-independent `packages` table has the same columns on every host.

## Contents

**Event tables**

-   Process Events: linux\_fork, linux\_exec, linux\_exit
-   Inventory Events: packages

**Common types**

Credentials, Namespaces, Cgroup, Process, Lineage, Filesystem, FileIdentity, Digest, File, FileDescriptor, Tty, Image, WorkloadOwner, KubernetesPod, Container

## Base Fields

Every Linux telemetry table carries these identity and timing columns.

Field

Type

Description

EventID

text

Unique identifier for the event

MachineID

text

The unique machine ID (host UUID)

Hostname

text

The hostname of the machine at the time of the event

BootID

text

The kernel’s boot identifier, stable for the lifetime of one boot

EventTime

timestamp

When the event occurred

ProcessedTime

timestamp

When Workshop processed the event

OperatingSystem

text

The platform the telemetry came from, always `linux` in these tables

## Process Events

### linux\_fork

A process creating another process. `SharedThreadGroup` is what separates a new thread of the same program from a genuinely independent process, and it decides that on its own. `SharedMm` and `SharedFiles` each report one resource shared independently of that: a thread commonly shares both, but neither is required for thread-group membership, and either can be shared by a task that is a separate process.

Field

Type

Description

Subject

Lineage

The process performing the creation, with the process that started it

Object

Process

The newly created process

SharedThreadGroup

boolean

Whether the new task joined its creator’s thread group, making it a thread of the same program

SharedMm

boolean

Whether the new task shares its creator’s address space

SharedFiles

boolean

Whether the new task shares its creator’s file descriptor table

Container

Container

The container the subject ran in. Absent when it ran directly on the host

### linux\_exec

A process replacing itself with a new program.

Field

Type

Description

Subject

Lineage

The process performing the execution and the process that started it, as they are after the change took effect

Comm

text

The short name the new program will be known by, at most 16 characters. Chosen by the program, so not evidence of what ran

Executable

File

The canonical path of the executable image that actually ran

Invoked

File

What was asked for. For a script this is the script, where `Executable` is the interpreter

Interpreted

boolean

Whether `Invoked` and `Executable` differ because an interpreter handled the request

WorkingDirectory

File

The working directory, needed to make sense of any relative path in `Args`. Only `Path` and `Type` are populated

Root

File

The process’s root directory, which is how a process confined to a subtree becomes visible. Only `Path` and `Type` are populated

FileDescriptors

FileDescriptor array

The standard descriptors the program inherited

Tty

Tty

The terminal the process is attached to

Args

text array

Command-line arguments

Envs

text array

Environment variables

Argc

number

An upper bound on how many entries `Args` holds, not a guarantee

ArgvEnvpCopied

number

Bytes of arguments and environment captured. Zero when capture failed outright

ArgvEnvpTruncated

boolean

When set, the absence of an expected argument means nothing

Container

Container

The container the subject ran in. Absent when it ran directly on the host

### linux\_exit

A process terminating. `Signal` is meaningful only when `ExitFromSignal` is set, and `ExitStatus` only when it is not. `ExitCode` is retained so nothing is lost, but it cannot be interpreted without `ExitFromSignal`; read the decoded fields instead.

Field

Type

Description

Subject

Lineage

The terminating process, with the process that started it

ExitCode

number

The raw packed status value a waiting parent receives. Cannot be interpreted without `ExitFromSignal`; read `Signal` and `ExitStatus` instead

ExitFromSignal

boolean

Whether the process was killed by a signal rather than ending on its own

Signal

number

The signal that killed the process, meaningful only when `ExitFromSignal` is set

ExitStatus

number

The status the process chose to end with, meaningful only when `ExitFromSignal` is not set

CoreDumped

boolean

Whether a memory dump was started, not that one was completed or written anywhere

GroupDead

boolean

Whether a whole program ended, as opposed to one thread of a still-running program

Container

Container

The container the subject ran in. Absent when it ran directly on the host

## Inventory Events

Unlike every other table on this page, inventory tables are not populated by the continuous telemetry stream. They are produced on demand by the Package Inventory command (**Hosts → Commands → Run command**), which asks each targeted host to run a read-only scan and upload the results into its normal telemetry prefix. A host that has never been scanned has no rows.

Two consequences worth knowing when querying:

-   **`BootSessionUUID` is always empty.** An on-demand scan isn’t tied to a boot session.
-   **`EventTime` is the scan time**, not the time a package was installed — the scan observes current state and has no visibility into when it came to be.

### packages

One row per package discovered on a host. Every ecosystem shares this single table, distinguished by `Ecosystem`, so a fleet-wide query needs no unions.

Field

Type

Description

EventID

text

Unique identifier for the inventory record

MachineID

text

The unique machine ID (host UUID)

Hostname

text

The hostname of the scanned host

BootSessionUUID

text

Always empty because an inventory scan is not tied to a boot session

EventTime

timestamp

When the inventory scan observed the package

ProcessedTime

timestamp

When Workshop processed the inventory record

OperatingSystem

text

The platform the scanned host is running

RecordType

text

Always `package` in this table

RunID

text

Identifier shared by every row from one scan; use it to isolate a single scan’s results

Profile

text

Scan profile that produced the row: `baseline`, `project`, or `deep`

Ecosystem

text

`npm`, `pypi`, `go`, `rubygems`, `packagist`, `mcp`, `editor-extension`, `browser-extension`, `homebrew`, `agent-skill`, or `nix`

PackageName

text

Package name as written in the manifest or lock file

NormalizedName

text

Ecosystem-normalized name — join on this rather than `PackageName`

Version

text

Installed version. Empty when no exact version could be determined

ProjectPath

text

Root of the project the package belongs to, for project-scoped finds

RootKind

text

Why the containing directory was walked: `global_package_root`, `user_package_root`, `project_root`, `editor_extension_root`, `browser_extension_root`, `mcp_config_root`, `homebrew_root`, `agent_skill_root`, `deep_home_root`, or `unknown`

InstallScope

text

Ecosystem-specific dependency scope (e.g. `prod`/`dev` for npm and pnpm, `indirect` for Go modules)

PackageManager

text

Manager that installed the package (e.g. `npm`, `pnpm`, `homebrew`, `firefox-extension`)

SourceType

text

Kind of evidence the row came from (e.g. `package.json`, `browser-extension`)

SourceFile

text

Path to the manifest, lock file, or metadata file the row was read from

DirectDependency

boolean

Whether the package is directly depended on rather than transitive. Null when the ecosystem can’t distinguish

HasLifecycleScripts

boolean

Whether the package declares install-time lifecycle scripts — these execute on install, so they are a supply-chain execution surface

LifecycleScripts

text array

Names of the declared lifecycle scripts

Confidence

text

How certain the identification is: `high`, or `medium` when the name or version had to be inferred

RequestedSpec

text

For MCP entries configured by spec, the requested selector (e.g. `@playwright/mcp@latest`) with `PackageName` normalized to the bare name

LocalAlias

text

Local name assigned in a config file, where that differs from the package it resolves to. Set only for `mcp` (the key under `mcpServers`) and `agent-skill` (the local skill name)

## Common Nested Types

The following types are used throughout the Linux telemetry schema to represent shared data structures.

### Credentials

The identity a process runs as. Two sets are carried on every process: the real set records who started it, the effective set is what permission checks are made against, so a program that has changed identity is still attributable to whoever launched it.

Field

Type

Description

UID

number

The real owner of the process, and who is able to signal it

GID

number

The real group of the process

SUID

number

Saved user ID, which a process that has dropped privilege can return to

SGID

number

Saved group ID, the group equivalent of `SUID`

EUID

number

The process’s privileges for most non-filesystem access

EGID

number

The group equivalent of `EUID`

FSUID

number

The identity used when accessing filesystem objects

FSGID

number

The group equivalent of `FSUID`

CapInheritable

number

Inheritable capability set, as a bitmask

CapPermitted

number

Permitted capability set, as a bitmask

CapEffective

number

Effective capability set, as a bitmask

CapBounding

number

Bounding capability set, as a bitmask

CapAmbient

number

Ambient capability set, as a bitmask

Securebits

number

The securebits flags in force for the process

### Namespaces

The isolated views of system resources a process sits in. Each value identifies one view: two processes sharing a value share that resource, and differing values are the clearest signal that a process is isolated from the host, whether by a container runtime, a sandbox, or a program that has isolated itself. These are operating system namespaces and have nothing to do with the Kubernetes namespace on KubernetesPod.

Field

Type

Description

UTS

number

Hostname and domain name

IPC

number

Shared memory, semaphores and message queues

Mnt

number

Which filesystems are mounted, and where

PID

number

Which other processes are visible, and under what numbers

PIDForChildren

number

The view processes started from here will be placed in. Differs from `PID` only between requesting a new view and starting the first child

Net

number

Network interfaces, addresses, routes and ports

Time

number

The system clock offsets a process observes

TimeForChildren

number

Same requester-versus-children distinction as `PIDForChildren`

Cgroup

number

How much of the resource-control hierarchy is visible from here

User

number

How user and group identities map to those on the host, which is how an unprivileged user can appear as an administrator inside a container

### Cgroup

The resource-control group a process belongs to, as opposed to `Namespaces.Cgroup`, which describes only how much of the hierarchy the process can see. A process is always in one, container or not.

Field

Type

Description

ID

number

Unique for as long as the group exists and not reused while it does, which makes it the key for attributing a process to a container

Level

number

How far below the root of the hierarchy the group sits, where zero is the root itself. A container’s group is never at the root

### Process

A running program, or one thread of it. PID alone does not identify a process over time because process numbers are recycled; PID together with `StartBoottime` does, within one boot of the host. Build identity on `StartBoottime` rather than `StartTime`, which is derived from the wall clock and inherits its error.

Field

Type

Description

PID

number

Process ID as seen from the host

NSPID

number

Process ID as seen inside the process’s own PID namespace

TGID

number

Thread group ID, the ID of the program this thread belongs to

NSTGID

number

Thread group ID as seen inside the process’s own PID namespace

StartBoottime

number

Nanoseconds since boot at which the process started

StartTime

timestamp

Wall-clock time the process started

PGID

number

Process group ID

SID

number

Session ID

LoginUID

number

The user who logged in, surviving later changes of identity. `4294967295` when unset

SessionID

number

An identifier for that login. `4294967295` when unset

RealCredentials

Credentials

The identity the process was started with

Credentials

Credentials

The identity the process runs as now

Namespaces

Namespaces

The kernel namespaces the process sits in

Cgroup

Cgroup

The specific resource-control group the process belongs to, as opposed to `Namespaces.Cgroup`, which describes only how much of the hierarchy it can see. The primary key for attributing a process to a container

Executable

File

The running program. Only `Identity` is populated here

NoNewPrivs

boolean

Whether the process is barred from gaining privileges through `exec`

### Lineage

A process together with the process that started it, captured at the same moment so the pair is internally consistent.

Field

Type

Description

Task

Process

The process itself

Parent

Process

The process that started it

### Filesystem

The filesystem a file resides on. Where a file lives is often as telling as what it contains: an executable on an in-memory or layered filesystem did not come from the host’s own installation.

Field

Type

Description

Type

text

Coarse filesystem type, e.g. `FILESYSTEM_TYPE_OVERLAYFS`, `FILESYSTEM_TYPE_TMPFS`

Magic

number

The exact filesystem magic value the kernel reported, set even when `Type` is unknown

### FileIdentity

What distinguishes one file from another independently of the name it is reached by. Two observations agreeing on `Dev` and `Ino` describe the same file even under different paths; agreeing on `Size` and `Mtime` as well means it has not changed in between.

Field

Type

Description

Dev

number

Device ID

Ino

number

Inode number

Size

number

File size in bytes

Atime

timestamp

Last access time

Mtime

timestamp

Last modification time

Ctime

timestamp

Last status change time

### Digest

A measurement of a file’s contents, which is what allows the same binary to be recognised wherever it appears and however it is named.

Field

Type

Description

Algorithm

text

Digest algorithm, e.g. `HASH_ALGORITHM_SHA256`

Value

text

Hex-encoded digest value

Valid

boolean

False when no measurement was available, in which case the other fields are meaningless

### File

Everything known about a single file. Any observation populates the subset it actually has, so an absent field means “not observed”, never “observed to be empty”.

Field

Type

Description

Path

text

File path

Identity

FileIdentity

Device, inode, size and timestamps

Type

text

The kind of file, e.g. `FILE_TYPE_REGULAR`

Filesystem

Filesystem

The filesystem the file resides on

Digest

Digest

Measurement of the file’s contents

Deleted

boolean

Whether the file had already been removed when it was observed. Null when the file itself was not inspected

PathTruncated

boolean

Whether `Path` ran out of room before it was complete. Null exactly where `Path` was not observed

### FileDescriptor

A numbered channel a program inherited when it started. Only 0, 1 and 2 are reported. A pipe or socket where a terminal is expected is a strong indication that a program’s output is being captured.

Field

Type

Description

FD

number

File descriptor number

File

File

What the descriptor refers to

### Tty

The terminal a process is attached to.

Field

Type

Description

Major

number

Major device number

Minor

number

Minor device number

Name

text

Terminal device name

Present

boolean

False for a service, which has no terminal; the other fields then carry nothing

### Image

The image a container was created from.

Field

Type

Description

Reference

text

The image reference, which is mutable and reusable

Digest

text

The image digest, which is stable and always means one image

### WorkloadOwner

What ultimately created and owns a pod. A pod’s own name is generated and replaced every time it is rescheduled, so this is the durable identity to attribute activity to.

Field

Type

Description

Kind

text

Controller kind, e.g. `Deployment`. Clusters routinely add their own kinds

Name

text

Controller name

### KubernetesPod

Where a container sits within an orchestrator, populated only when the host is managed by one. `Namespace` here is a Kubernetes namespace, a tenancy boundary within a cluster, which is a wholly different concept to the kernel Namespaces on a process. Nothing relates the two.

Field

Type

Description

Name

text

Pod name, regenerated whenever the pod is rescheduled

Namespace

text

Kubernetes namespace the pod runs in

UID

text

Pod UID

ContainerName

text

Name of the container within the pod

Owner

WorkloadOwner

The controller that owns the pod

ServiceAccount

text

The identity the pod’s processes present to the cluster

### Container

The container an event occurred inside. `CgroupPath` is observed directly and is present whenever the activity happened inside any resource-control group. Everything below it is resolved against the local container runtime and is absent when the runtime is unknown or unreachable, or when the activity did not happen inside a container at all.

Field

Type

Description

CgroupPath

text

The cgroup path the activity happened in

Runtime

text

The container runtime, e.g. `CONTAINER_RUNTIME_DOCKER`

ID

text

Container ID

Name

text

Container name

Image

Image

The image the container was created from

Labels

map(text, text)

Labels attached at creation, carried whole

Pod

KubernetesPod

Orchestrator attribution, when the host is managed by one

## Sitemap

- [Home](https://northpole.security/index.md)
- [Workshop](https://northpole.security/workshop.md)
- [Santa](https://northpole.security/santa.md)
- [Features](https://northpole.security/features.md)
- [Cookbook](https://northpole.security/cookbook.md)
- [Docs](https://northpole.security/docs.md)
- [Blog](https://northpole.security/blog.md)
- [Glossary](https://northpole.security/glossary.md)
- [About](https://northpole.security/about.md)
- [Contact](https://northpole.security/contact.md)
