kernel enforcement for AI agents

Reality Kernel

Your agent can run commands. The kernel decides which ones happen.The kernel watches, and writes down what it would stop.

Network, exec and file policy decided in eBPF, inside the Linux kernel, before the action takes place. Every decision lands in a signed, tamper-evident audit log.

  • Linux 5.15 and newer
  • x86_64 · arm64
  • MIT OR Apache-2.0

the warden · mode = "enforce" · denied calls get EPERMthe warden · mode = "audit" · would-deny calls are logged

$ rk audit tail -f

  • 09:14:02.118Z DENY Open 203.0.113.7:443/tcp rule 4 (research-agent)
  • 09:14:02.451Z DENY Launch /usr/bin/curl rule 9 (research-agent)
  • 09:14:03.007Z DENY Open /home/agent/.ssh/id_ed25519 rule 12 (research-agent)
  • 09:14:05.630Z DENY Open 169.254.169.254:80/tcp rule 2 (research-agent)
  • 09:14:07.212Z DENY Launch /tmp/x rule 9 (research-agent)
  • 09:14:02.118Z AUDIT Open 203.0.113.7:443/tcp rule 4 (research-agent)
  • 09:14:02.451Z AUDIT Launch /usr/bin/curl rule 9 (research-agent)
  • 09:14:03.007Z AUDIT Open /home/agent/.ssh/id_ed25519 rule 12 (research-agent)
  • 09:14:05.630Z AUDIT Open 169.254.169.254:80/tcp rule 2 (research-agent)
  • 09:14:07.212Z AUDIT Launch /tmp/x rule 9 (research-agent)

the boundary

Guardrails can be talked around. The kernel can't.

Prompt filters and tool wrappers sit in front of the agent. A prompt injection, a bug or a child process can step around them. Reality Kernel attaches eBPF programs to the kernel's BPF-LSM and cgroup socket hooks, so the decision is made at the system call, for every process in a governed cgroup, however the request was phrased.

Inside the agentstrace, abridged
$ rk run --profile research-agent -- python3 agent.py
connect(3, {AF_INET, 203.0.113.7:443}) = -1 EPERM
execve("/usr/bin/curl", ...)          = -1 EPERM
openat("~/.ssh/id_ed25519", O_RDONLY)  = -1 EPERM
connect(3, {AF_INET, 10.20.0.12:443}) = 0
BPF-LSM · cgroup hooks
On the hostrk audit tail, abridged
$ rk audit tail -f --verdict deny
09:14:02Z DENY  Open   203.0.113.7:443/tcp    rule 4
09:14:02Z DENY  Launch /usr/bin/curl          rule 9
09:14:03Z DENY  Open   ~/.ssh/id_ed25519      rule 12
$ rk audit verify
VERIFIED
Example session: an agent's denied connect, exec and open calls return EPERM, and the host's audit log records each decision.

what it enforces

Every capability links to its tests.

The project keeps a map from every claim to the named tests behind it, and CI checks that those tests passed on every supported kernel. Follow any link to see them.

// net

Denies governed connections over TCP and UDP, IPv4 and IPv6, and closes the usual bypasses: raw and packet sockets, io_uring, TCP Fast Open and NAT64 addresses.

net-enforce-epermnet-bypasses

// exec

Allows only listed executables, decided on file identity rather than path, so symlinks, replaced binaries, scripts and memfd tricks do not get around it.

exec-allowlistexec-identity

// files

Protects files per access type: read, write, delete, rename, link, create and setattr, whatever name the file is reached by.

file-access-typesfile-identity

// audit

Records every deny and audit-would-deny as an OCSF record in a hash-chained log signed with Ed25519. rk audit verify detects any edit.

audit_completeaudit_tamper

how it works

From policy file to kernel decision

  1. Write a profile

    A TOML profile lists the networks, executables and files an agent may use. Start it in audit mode to see what it would deny, then switch to enforce.

  2. Compile and swap

    The sensor validates the policy, compiles it into BPF maps and switches to it in one atomic step. rk policy rollback undoes it.

  3. Bind the workload

    rk run or the Kubernetes NRI plugin places the agent in its own cgroup, bound to the profile before its first instruction.

  4. Decide and record

    Each governed system call is allowed or refused with EPERM in the kernel. The decision streams to the audit log, Prometheus metrics and OpenTelemetry traces.

quick start

Install. Check the host. Govern an agent.

Packages for Debian, Ubuntu, RHEL and Rocky, a Helm chart for Kubernetes, and static binaries. Releases are signed with Sigstore and carry SLSA provenance and an SBOM.

shell
# install the package from the latest release
sudo dpkg -i reality-kernel_<version>-1_amd64.deb
# check kernel features; it explains any gap
rk doctor
# define a profile, then reload
sudoedit /etc/rk/policy.toml
sudo systemctl reload rk-sensor
# run an agent under it, and watch the decisions
rk run --profile research-agent -- python3 agent.py
rk audit tail -f
/etc/rk/policy.toml
[profiles.research-agent]
mode = "enforce"
network.default = "deny"

[[profiles.research-agent.network.allow]]
cidr = "10.20.0.0/16"
ports = ["443"]
proto = ["tcp"]

[profiles.research-agent.exec]
allow = ["/usr/bin/python3", "/usr/bin/git"]

[[profiles.research-agent.files.deny]]
path = "/home/agent/.ssh"
subtree = true
access = ["all"]

tested where it runs

Every acceptance test runs on real kernels

Kernel behaviour differs between versions, so the integration suites run as root in a virtual machine for each supported kernel instead of against mocks.

  • 5.15LTS · minimum
  • 6.1LTS
  • 6.6LTS
  • 6.12LTS
  • 6.18stable
  • Kernel suites run on x86_64; arm64 builds and runs the unit tests in CI.
  • The same policy test cases run against the userspace evaluator and the kernel, so the two cannot drift apart.
  • Packages are installed, upgraded and removed on Ubuntu 24.04 and Rocky Linux 9, with a probe checking that enforcement never pauses.
  • A Kubernetes cluster runs the Helm chart and the NRI plugin.

See the evidence for every claim

get involved

Put the kernel between your agents and the host.

Reality Kernel is developed in the open. Read the threat model, try it on a test host in audit mode first, and open an issue or a pull request.