Before Oligo, Eran and I spent years building infrastructure tools. The pattern we kept running into was this: a CVE would be disclosed, a CVSS score of 9.8 would get assigned, and teams would scramble to determine which of their services actually used the affected dependency. The scramble itself was often the first time anyone had a clear picture of what was running in production. The vulnerability existed. It had been running in production. Nobody knew exactly where.
That realization moved us toward runtime. Scanning improved: SCA tools mapped dependency graphs more effectively, and SAST expanded its language coverage. The core shortfall was not scan quality. It was the gap between a scan result and production reality. A Git repository scan shows what the code contains. It cannot show what is actually running at 2am while an attacker actively probes your services.
The Problem We Set Out to Solve
We kept coming back to one framing: what is the minimum information needed to know whether an application is being exploited right now? Not "does its dependency tree contain a critical vulnerability" (useful, but CVSS-scored remediation queues are long). Not "does the code contain an unsafe pattern" (also useful, but false positives are frequent and exploitability remains uncertain). The real question is whether this application, handling this traffic, shows the behavior exploitation would produce.
That requires observing the application at runtime rather than at rest. We need to see what it does under real conditions, at a layer the application cannot influence or deceive. That is why the kernel boundary is the right vantage point.
Why We First Rejected DAST and RASP
DAST tests a running application with attacker-like inputs and examines the responses. It finds genuine vulnerabilities in genuine running code. Its constraint is coverage: DAST can probe only endpoints it knows and can reach. It cannot see inside a background worker, an async job queue handler, or a microservice reachable only through other internal services. In an application made up of 15 microservices, DAST generally covers externally exposed services well and internal services poorly.
RASP (Runtime Application Self-Protection) instruments the application internally, usually through a JVM agent, Python hook, or language-specific instrumentation library. It can see application behavior beyond DAST's reach. The cost is integration: each application needs code or deployment pipeline changes. For a team operating dozens of services across multiple languages, that creates a substantial maintenance burden. More importantly, RASP runs inside the application's process space, so an attacker with sufficient control of execution can disable the protection layer.
Neither option matched our goal.
Why eBPF Fit the Need
eBPF programs run in kernel space and are checked by the kernel's verifier before loading. A compromised application process cannot disable them. They observe every system call, network event, and file operation for every process on the node, regardless of language or runtime. No per-application agent, linked library, or JVM flag is required.
The production safety question around kernel-level instrumentation is real, and it was central to our early design work. Before eBPF, a faulty kernel module could crash the kernel. At load time, the eBPF verifier checks safety properties: the program must terminate (with no unbounded loops unless kernel 5.3+ bounded loop support applies), cannot dereference arbitrary pointers without validation, and cannot access memory beyond permitted regions. A BPF program that fails verification is rejected before execution. That makes eBPF suitable for production without the stability concerns associated with traditional kernel modules.
The performance cost of eBPF instrumentation is real, but bounded and measurable. A kprobe firing on sys_enter_execve adds a small cost to each execve syscall. For a service that rarely calls execve, the overhead is negligible. When a service calls execve frequently, such as a CI runner or shell-heavy build system, we use sampling and rate limiting. The observation cost can be tuned, unlike RASP's in-process interception of every method call.
Language-Agnostic by Design
The polyglot character of production environments was a major reason we chose eBPF. A typical service mesh contains Java, Python, Go, and Node.js services, often with C++ or Rust at the edge. An approach requiring a language-specific agent means separate implementation, maintenance, and coverage gaps for every language.
eBPF works beneath the language layer. Every language runtime makes syscalls, every network connection passes through the kernel, and every file operation appears at the VFS layer. Language-agnostic instrumentation was not an extra design decision on top of eBPF. It follows from where eBPF observes.
What We Do Not Claim
Using eBPF does not make scanning unnecessary. Every service we protect should still receive SCA scanning for dependency vulnerabilities, SAST for code patterns, and DAST for externally accessible attack surface. Runtime observation closes the gap between scan findings in code and events in production. It does not replace scanning.
The early access program opened at the beginning of 2025 provided our first real data on detection logic against actual workloads. Behavioral baseline deviation produced more false positives than expected for services with highly variable workload patterns, prompting the rolling deployment handling described in our baselining post. Detection fidelity for known-bad patterns, including shell spawn from a web process and outbound LDAP from a JVM, matched the theoretical model exactly. The kernel does not misrepresent what processes are doing.