Skip to content

Sensor permissions

The sensor is the agent that runs on each node, one pod per node as a DaemonSet. It watches network traffic, encrypted traffic before it’s encrypted, and CPU usage, using eBPF programs in the Linux kernel. That needs more access than an ordinary pod, so this page lists exactly what it gets and what it does with it.

The sensor sends what it records only to your own core (the ingest gateway in your cluster, or a remote site’s aggregator). Its only other connection is to your cluster’s Kubernetes API, described below.

By default (sensor.privileged: false) the sensor is not a privileged container. It drops every capability, including the container runtime’s defaults, and adds back only these:

Capability Why
BPF Load its eBPF programs and maps.
PERFMON Attach those programs to kernel functions and sample CPUs for profiles.
SYS_PTRACE Read other processes’ /proc/<pid>/exe, maps and root, to find the TLS libraries and Go binaries to watch.
SYS_ADMIN Ubuntu kernels refuse user-space probes (needed for TLS capture) without it.
SYSLOG Read kernel symbol addresses, so CPU profiles can name kernel functions.

We measured this set against a privileged run on Ubuntu 24.04 and GKE nodes: both capture the same data.

Also in its security context:

  • seccomp stays on, with the runtime’s default profile.
  • Read-only root filesystem.
  • AppArmor unconfined. The container profile hides other processes’ /proc entries even with SYS_PTRACE, which would stop TLS capture.
  • allowPrivilegeEscalation isn’t set to false: Kubernetes rejects that setting alongside SYS_ADMIN.

On hosts whose security module refuses this set, such as SELinux-enforcing Bottlerocket or OpenShift nodes, the sensor logs attach_failed or /proc access denied warnings. Set sensor.privileged: true there to run it as a privileged container instead.

Access Why
hostPID: true See every process on the node, to match traffic to the pod that made it.
/sys, read-only Kernel type information (BTF) to run one build on many kernels, and the cgroup tree for per-container CPU and memory.
/proc, read-only, at /host/proc The node’s real CPU and memory figures.

It doesn’t use the host network, write to the host, or mount the container runtime’s socket.

A ClusterRole with get, list and watch on pods and nodes, to name the workload behind each connection. Nothing else: no secrets, no config maps, no write access of any kind.

Traffic Recorded
Every TCP connection Source and destination address and port, bytes each way, round-trip time, and the pod on each end.
HTTP/1 and HTTP/2 Method, path with the query string removed, route, host, status code and timing. From responses, only rate-limit headers.
gRPC Service, method and status.
PostgreSQL and MySQL The statement, with literal values replaced by ? (sensor.scrubSqlLiterals, on by default), the table, and error codes.
Redis The command and the key name, never the value.
MongoDB The operation and collection.
Kafka The operation and client ID.
DNS The name looked up, its record type and the response code.
Language-model API calls Which provider was called, timing, errors and rate limiting. Never the prompt or the response.
CPU profiles Sampled stack traces, named down to the function.

For each request it also records the process name and ID that made it.

  • Request and response bodies, including form posts, JSON payloads, prompts and model output.
  • Request headers other than the host, so never Authorization, cookies or API keys.
  • Query strings, where tokens and personal data often travel.
  • SQL literal values, which hold data such as emails or passwords in ALTER USER, unless you turn scrubSqlLiterals off.
  • Redis values.

TLS capture reads traffic inside your processes, before it’s encrypted or after it’s decrypted. The same rules apply to it: the sensor parses it in memory, keeps only the fields above, and discards the rest. It never handles private keys.

Token counts and model names come from your applications’ own LLM instrumentation, if you use it. Those libraries can record prompts and responses too, so the ingest gateway removes that text from every span before it’s stored.

Logs aren’t collected by the sensor. The optional log collector (logCollector, off by default) forwards your pods’ standard output and error, which hold whatever your applications write there.