Watch the kernel, not the log file
Falak Neo attaches CO-RE eBPF programs to the syscall and LSM paths that carry security meaning, drains them from a ring buffer in a Rust userspace that never blocks the kernel, and constructs OCSF events on the host. What reaches your detection pipeline is what the kernel observed, not what an application decided to report.
- Process exec and exit with full ancestry
- File access with in-kernel sensitivity classification
- Socket connect and accept, distinguished by syscall
- DNS parsed on the socket path, no resolver hook
- bpf(), ptrace and kernel module loads
- Under 1% CPU on a busy production node
Capabilities
What it does
Process ancestry that survives the process
Every exec carries parent_process plus a flattened ancestry array. When an analyst opens a finding an hour later, the tree is reconstructable even though every process in it has exited — it is history, not a live /proc walk.
Fileless execution provenance
The sensor sets exec_from_memfd, exec_from_tmpfs and exec_deleted_binary at exec time by resolving the executable's inode. A payload that never touches disk is exactly the case where file integrity monitoring has nothing to say.
Sensitive-path classification in-kernel
File events are tagged with a path_class — credential, persistence, anti-forensics, staging — before they leave the kernel. That is what makes a credential-access rule cheap enough to run everywhere rather than sampled.
Network events with syscall origin
A connect() and an accept4() both produce a 4001 Network Activity event, but the syscall field distinguishes them. Lateral-movement analytics need that difference; a netflow record does not have it.
Filters and sampling that are auditable
Noise suppression is policy, expressed as path prefixes, process names, CIDRs and namespaces, with an always-include list that no exclusion can override. You can read exactly what the fleet is not looking at.
Response the sensor can refuse
Kill process, isolate host, quarantine file, stop container. Each is signed by core with an expiry, and the sensor refuses anything unsigned, expired, or addressed to a different agent. A compromised console cannot execute across a fleet.
Detections
Representative detection content
| Detection | Technique | Primary signal |
|---|---|---|
| Fileless execution from memfd | T1620 | exec_from_memfd == true |
| Reverse shell with socket stdio | T1059.004 | exec + connect within 5s |
| /etc/shadow read outside the auth stack | T1003.008 | path_class == credential |
| SSH authorized_keys written | T1098.004 | 1001 create/update |
| Setuid binary dropped then executed | T1548.001 | chmod 04xxx → exec |
| Kernel module from a writable path | T1547.006 | finit_module outside /lib/modules |
| Unexpected bpf(BPF_PROG_LOAD) | T1562.001 | 1003 kernel activity |
| System log truncated or shredded | T1070.002 | unlink under /var/log |
Telemetry collected
- Process activity
- OCSF 1007
- File system activity
- OCSF 1001
- Network activity
- OCSF 4001
- DNS activity
- OCSF 4003
- Kernel activity
- OCSF 1003
- Module activity
- OCSF 1005
- Authentication
- OCSF 3002
- Steady-state CPU
- 0.3 – 0.9%
- Resident memory
- ~80 MiB
probe attachment reported on every heartbeat
probe_state: sched_process_exec: attached sched_process_exit: attached sys_enter_connect: attached sys_enter_accept4: attached file_open: attached # bpf_lsm, kprobe fallback bpf: attached ptrace: attached module_load: attached dns: attached # A failed probe is a visibility gap, not a warning. # The console reads probe state, not just rule state, # when it computes ATT&CK coverage.
Start with one node
Install the sensor on a single host, watch what it emits for an hour, and decide from the events rather than from a datasheet. The quickstart takes about five minutes.