
eBPF Security Monitoring and Sandboxing Agent Based on Aya
Bombini is an eBPF-based security agent written entirely in Rust using the Aya library and built on LSM (Linux Security Module) BPF hooks. At its core, Bombini employs modular components called Detectors, each responsible for monitoring and reporting specific types of system events. Detectors with sandbox mode enabled also block forbidden actions right in the kernel.
EPERM instead of being reported
once it has already happened.scope/event predicates
either report an event or, with sandbox enabled, deny it.Bombini needs Linux 6.2+ with BPF LSM enabled. Check the compatibility notes first. The container image is built for x86_64.
Start Bombini with the quickstart config from the repository root:
docker run --pid=host --rm -it --privileged \
-v $PWD/examples/quickstart:/usr/local/lib/bombini/config:ro \
-v /sys/fs/bpf:/sys/fs/bpf \
ghcr.io/bombinisecurity/bombini:v1.1.0
The config consists of three detector files.
procmon.yaml reports setuid to root and forbids
executing anything from /tmp:
# Detect privilege escalation to root
setuid:
enabled: true
rules:
- rule: SetUidToRoot
event: euid == 0
# Block binaries executed from /tmp right in the kernel
bprm_check:
enabled: true
sandbox:
enabled: true
deny_list: true
rules:
- rule: DenyExecFromTmp
event: path_prefix == "/tmp"
filemon.yaml reports reads of /etc/shadow:
# Detect reads of password hashes
file_open:
enabled: true
rules:
- rule: ShadowRead
event: path == "/etc/shadow"
netmon.yaml reports connections to the cloud
metadata service:
# Detect access to the cloud metadata service: a common way to steal credentials
egress:
enabled: true
rules:
- rule: CloudMetadataAccess
event: ipv4_dst == "169.254.169.254" AND port_dst == 80
Generate events in another terminal:
$ ./examples/quickstart/trigger.sh
[1] sudo reads /etc/shadow: Setuid and FileOpen events
[2] exec a binary from /tmp: blocked by the sandbox
./examples/quickstart/trigger.sh: 10: /tmp/bombini-quickstart: Operation not permitted
blocked: exit code 126
[3] connect to the cloud metadata service: Egress event
Bombini prints events to stdout as JSON lines. This is the blocked exec:
{
"type": "ProcessEvent",
"process": {
"start_time": "2026-10-03T14:36:10.256Z",
"cloned": true,
"pid": 39988,
"tid": 39988,
"ppid": 39984,
"uid": 503,
"euid": 503,
"gid": 1000,
"egid": 1000,
"auid": 0,
"cap_inheritable": "",
"cap_permitted": "",
"cap_effective": "",
"secureexec": "",
"filename": "dash",
"binary_path": "/usr/bin/dash",
"args": "./examples/quickstart/trigger.sh",
"exec_id": "Mzk5ODg6MjEyNzU3NDAzMjI2MzI2",
"parent_exec_id": "Mzk5ODQ6MjEyNzU3MzgzNTY5NTc3"
},
"parent": { "...": "same fields for the parent process" },
"blocked": true,
"process_event": {
"type": "BprmCheck",
"binary": "/tmp/bombini-quickstart"
},
"timestamp": "2026-10-03T14:36:10.256Z",
"rule": "DenyExecFromTmp"
}
More ready-made policies, such as GTFOBins shell escapes and privilege escalation, are in examples.
| Detector | What it watches | Sandbox |
|---|---|---|
| ProcMon | Process execs and exits, setuid/setgid, capabilities, prctl, user namespaces, ptrace | ✓ |
| FileMon | File open, mmap, truncate, unlink, symlink, chmod, chown, mount, ioctl | ✓ |
| NetMon | Ingress and egress TCP connections, socket creation and connect | ✓ |
| KernelMon | BPF map creation, BPF program loads, and access to BPF maps and programs | |
| IOUringMon | io_uring submission queue entries | |
| SysEnumMon (experimental) | System enumeration: several watched files or binaries touched within a time window |
The rule syntax is described in Rules, and the event format in Events.
Full documentation is in the book.
Please, check out CONTRIBUTING.md for the contributing guideline.