{"slug": "the-kernel-does-not-care-what-you-named-the-tool", "title": "The kernel does not care what you named the tool", "summary": "AgentGuard, an Apache-2.0 Linux eBPF LSM supervisor for coding agents, launched at version 0.1.2 as an early prototype that enforces security policy at the kernel level rather than inside the agent. The tool loads YAML policy from policies/default.yaml to block access to credentials such as .env and id_rsa, destructive argv like rm and dd, and non-allowlisted egress on port 443, returning EPERM on denial. AgentGuard is tested primarily with Claude Code and wired the same way for Codex, but native Darwin claude is not supervised because macOS has no BPF LSM.", "body_md": "[Back to blogs](/blogs)\n\nSeptember 8, 2026\n\n# The kernel does not care what you named the tool\n\n**AgentGuard:** eBPF LSM for coding agents. YAML in the repo. Deny is `EPERM`.\n\nLinux prototype · Apache-2.0 · [github.com/AgentGuard-hq/AgentGuard](https://github.com/AgentGuard-hq/AgentGuard)\n\nYou asked the agent to fix a failing test. The GitHub issue looked normal. Buried in a fixture, or in an MCP response, or in a `README` the model helpfully fetched, was an instruction to read `.env` and post it somewhere.\n\nThe model may even *agree* that secrets are off-limits. That is not a security boundary. The boundary is whether `openat` succeeds.\n\nCoding agents are not chatbots with a nicer prompt. They `open`, `exec`, and `connect`. The failure that matters is the **next syscall**, not the next token.\n\n## Conscience is not a TCB\n\nMost guardrails live *inside* the agent:\n\n- a system prompt\n- `CLAUDE.md` /`AGENTS.md`\n- `PreToolUse` hooks\n- an allowlist of “Bash” strings\n\nThose are a conscience. Consciences are bypassed the moment execution leaves the tool schema.\n\nDeny `.env` in a hook, then read it with `python -c`, `perl`, `node`, a loader, `mmap`, anything that is not `Read` or `Bash` as the CLI defines them. Deny `rm` as a command string, then hit the same inode another way. The hook never ran. The kernel still would — **if you asked it to**.\n\nVendor sandboxes (Seatbelt, bubblewrap, Claude’s `sandbox-runtime`, devcontainers) are the right *product* default for most people. This post is a narrower claim:\n\nPolicy that remains true when the agent’s own conscience is false.\n\nThat layer is the LSM. Deny is `EPERM`. The OS does not care what the tool was named.\n\n## What AgentGuard is\n\nAgentGuard is a **Linux eBPF LSM supervisor** for coding agents. One binary loads policy into the kernel and starts the agent as the invoking user, not root.\n\nPolicy is YAML in the project (`policies/default.yaml`). Starter rules:\n\n- **Credentials** — block`.env` ,`id_rsa` , the usual secret paths\n- **Destructive argv** —`rm` ,`dd` , the obvious ones\n- **Egress** — allowlisted hosts on 443, via a local proxy; everything else denied\n\nA deny is a kernel error, not a chat message. Optionally, Claude Code / Codex hooks inject a `feedback:` string so the model can *adapt* instead of spinning on a raw permission error. If the hooks are missing, **the kernel still blocks**. The model just is not told why.\n\nThat split is the whole design:\n\n| Layer | Job | \n|---|---|\n| LSM | Enforcement. Fail closed. | \n| YAML in git | Policy you can review in the PR. | \n| Hooks | Explanation. Courtesy. Not the TCB. | \n\n```\npolicies/default.yaml\n        │\n        ▼\n   eBPF LSM (loaded as root)\n        │\n        ▼\n   agent as SUDO_USER\n        │\n        ├── openat(\".env\")              → EPERM\n        ├── execve(\"rm\", …)             → EPERM\n        └── connect(not :443 allowlist) → EPERM\n                │\n                └── optional: \"SYSTEM FEEDBACK: …\" into the TUI\n```\n\nStatus: **v0.1.2**, early. Tested primarily with Claude Code. Codex is wired the same way. Native Darwin `claude` is **not** supervised — macOS has no BPF LSM. A Colima/Docker Linux VM is a different machine, not a magic halo around the host binary.\n\n## Why `EPERM` and not another hook\n\nHooks inspect *intent as the product serialized it*. LSM inspects *what the process did*.\n\nIf you only wrap `Bash`, you have not wrapped `python`. If you only wrap the CLI’s `Read` tool, you have not wrapped `openat` from a compiler, a test runner, or a postinstall script the agent just spawned. Child processes inherit the LSM. They do not inherit your `settings.json`.\n\nThat is also why AgentGuard is not “prompt injection detection.” Injection is how you *get* to a bad syscall. The interesting part is whether the syscall is allowed. Catching every encoding of “ignore previous instructions” is a language problem. Catching `openat` on `.ssh/id_rsa` is a kernel problem. I would rather have both. I will not pretend the first replaces the second.\n\n## Privilege, said plainly\n\nLoading BPF is a loaded privilege. Typically root at load, `CAP_BPF` in play.\n\nTwo rules I treat as non-negotiable:\n\n1. **LSM only.** The supervisor must not attach tracing probes on the agent’s TLS stack or rewrite userspace buffers. If you need to mutate what the model “saw” in order to “help,” you are no longer a reference monitor.\n2. **Pin the object. Drop caps on the child.**`doctor` should fail on a hash mismatch. The agent must not keep`CAP_BPF` . A second tracing program on the box is a*peer* of the supervisor, not a child you can YAML away — unless you also gate`bpf()` / program types.\n\n“We used eBPF” is not the same sentence as “you can trust us.” The first is a mechanism. The second is a TCB story: hashed program, allowlisted types, no extra helpers, agent running as a boring user.\n\n`install.sh` cannot invent `lsm=bpf`. That is a boot-time fact. If `doctor` says BPF is missing from the LSM list, that is the kernel cmdline, not a missing mount. Securityfs being readable is not the same as enforcement.\n\n## Non-goals (on purpose)\n\nAgentGuard is **not**:\n\n- a replacement for Anthropic’s Seatbelt / bubblewrap sandbox, MDM, or Claude Code on the web\n- a Mac-native enforcer\n- a hosted microVM product (that is E2B/Daytona/Modal)\n- a complete jail — the default YAML is a starter, completeness is a policy problem\n- unprivileged install on a random laptop kernel\n\nIf the threat model is “untrusted repo, don’t toast the laptop,” start with the first-party sandbox or a VM. Use something like this when you need **agent-agnostic, auditable syscall policy** on a Linux box you already control.\n\nThere are many other GitHub repos named AgentGuard. This one is the kernel one. The name collision is annoying and irrelevant to the claim.\n\n## What “working” looks like\n\nThe demo I care about is not a cartoon jailbreak.\n\n1. Hooks and `CLAUDE.md` say: never read`.env` , never`rm -rf` .\n2. The prompt is ordinary: debug the test / summarize the issue.\n3. The bypass does not go through the tool the hook subscribed to.\n4. Hooks-only: the secret is in context, or the file is gone.\n5. LSM: `EPERM` . Process still alive. Optional`feedback:` so the model retries cleanly.\n\nIf I cannot show a hook path that *loses* and an LSM path that *holds*, I do not have a product. I have a policy compiler with extra steps.\n\n## Why this exists\n\nI wanted to know whether coding-agent safety could live at the same layer as every other process on Linux: LSM, fail closed, policy in git.\n\nThe prototype says **yes**, with the usual kernel tax — BTF, `lsm=bpf`, sudo to load, no Darwin miracles.\n\nThe industry is shipping consciences at industrial scale. Some of them are good consciences. I still want the door to lock when the conscience is tired, confused, or prompt-injected.\n\nHooks are the agent’s conscience.\n\n**The kernel is the door.**\n\n*AgentGuard is Apache-2.0, v0.1.2, Linux. Code and a longer engineering note: [github.com/AgentGuard-hq/AgentGuard](https://github.com/AgentGuard-hq/AgentGuard).*", "url": "https://wpnews.pro/news/the-kernel-does-not-care-what-you-named-the-tool", "canonical_source": "https://www.cognivisehub.com/blogs/the-kernel-does-not-care-what-you-named-the-tool", "published_at": "2026-09-10 16:35:06+00:00", "updated_at": "2026-09-10 16:54:56.110978+00:00", "lang": "en", "topics": ["ai-agents", "ai-safety", "ai-tools", "developer-tools", "ai-policy"], "entities": ["AgentGuard", "Linux", "eBPF", "Claude Code", "Codex", "macOS", "Apache-2.0", "GitHub"], "alternates": {"html": "https://wpnews.pro/news/the-kernel-does-not-care-what-you-named-the-tool", "markdown": "https://wpnews.pro/news/the-kernel-does-not-care-what-you-named-the-tool.md", "text": "https://wpnews.pro/news/the-kernel-does-not-care-what-you-named-the-tool.txt", "jsonld": "https://wpnews.pro/news/the-kernel-does-not-care-what-you-named-the-tool.jsonld"}}