Runtime security for
AI agents

eBPF-based enforcement that blocks unexpected file access, network calls, and subprocess spawning — before they complete. Zero code changes in the agent.

Linux 5.7+ BPF LSM Go + C CO-RE Real-time UI
Install View source

How it works

AI agent (claude, gemini, ollama, ...) │ fork / exec / open / connect ▼ Linux Kernel BPF LSM hooks lsm/file_open → check blocked_paths map → -EPERM if denied lsm/socket_connect → check blocked_ipv4 map → -EPERM if denied lsm/bprm_check → check blocked_paths map → -EPERM if denied │ ring buffer events ▼ vigil daemon detector → evaluates against profile → ALLOW / BLOCK audit log → one JSON line per decision web UI → real-time SSE event feed

LSM hooks run synchronously inside the kernel before the syscall returns — the process never sees a file descriptor, socket, or child PID for a denied resource.

🔒

Inline enforcement

BPF LSM hooks block at the kernel boundary. Denied syscalls return -EPERM before any user-space code runs.

🧬

Process lineage

Tracks agent process trees by PID via fork/exec/exit tracepoints. No false positives from unrelated processes sharing the same comm name.

📡

Real-time UI

SSE-based web dashboard embedded in the binary. Every ALLOW and BLOCK event streams live with timestamps and process context.

CO-RE

Compiled once, runs across kernels. BTF-based relocation means one pre-built binary works on Ubuntu 22.04 through the latest kernel.

Install

One-liner (recommended)

curl -fsSL https://github.com/VectorInstitute/vigil/releases/latest/download/install.sh | sudo bash

Installs the vigil binary and built-in profiles to /usr/local/bin and /usr/lib/vigil/profiles.

Build from source

# Requires: clang, llvm, bpftool, linux-headers, Go 1.22+
git clone https://github.com/VectorInstitute/vigil
cd vigil
make        # builds BPF + Go binary

Enable BPF LSM

Add lsm=bpf to your kernel boot parameters:

# /etc/default/grub
GRUB_CMDLINE_LINUX="lsm=bpf"

sudo update-grub && sudo reboot

Usage

# Watch an AI agent with the built-in profile
sudo vigil watch --framework gemini-cli

# With real-time web UI at http://localhost:7394
sudo vigil watch --framework claude-code --ui --port 7394

# Custom profile
sudo vigil watch --profile /path/to/profile.yaml

# List built-in profiles
vigil profile list

Process lineage tracking

AI agents spawn many child processes — node, sh, python3, git — that share comm names with unrelated system processes. Without lineage tracking, vigil would either miss agent children or flood the event stream with noise from VS Code, SSH daemons, and cron jobs.

entry_comm in profile

Name the agent's root process. For Gemini CLI: entry_comm: gemini. For Claude Code: entry_comm: claude.

sched_process_exec tracepoint

When a process exec's to entry_comm, its PID is added to the watched_pids BPF hash map.

sched_process_fork tracepoint

When a watched PID forks, the child PID inherits membership in watched_pids automatically.

Observation filtered by PID

All syscall tracepoints check watched_pids before emitting an event. Only agent process tree events reach the ring buffer.

sched_process_exit tracepoint

PIDs are removed from watched_pids on exit, preventing false positives from PID reuse.

# profiles/gemini-cli.yaml
entry_comm: gemini   # root process to track

# gemini forks → node; vigil tracks node as part of gemini's tree.
# VS Code's node is a different PID lineage — completely invisible.

Profiles

Profiles define the expected behavioral envelope for an AI workload. Each profile specifies denied paths, allowed networks, allowed subprocesses, and the entry process to track.

Profile Entry process Default policy Status
ollama ollama deny Available
claude-code claude allow Available
gemini-cli gemini allow Available
vllm Coming soon
llamacpp Coming soon

Custom profile

name: my-agent
version: "1.0"
default_policy: allow
entry_comm: my-agent   # root process comm (max 15 chars)

denied_paths:
  - /etc/shadow
  - /root/.ssh/**
  - /**/.aws/credentials

allowed_networks:
  - 127.0.0.0/8
  - ::1/128
  - 0.0.0.0/0   # or restrict to specific CIDRs

allowed_commands:
  - my-agent
  - node
  - git