---
title: "Why Agent Plugins Are Not a Security Boundary: From Advisory Hooks to a Kernel-Enforced Agent Runtime"
subtitle: "When an autonomous agent shares a privilege domain with its supervisor, hooks and system prompts are merely polite suggestions. This monograph details how Aegis OS lowers the enforcement boundary into the OS kernel via parent-process sandboxing, read-only .git pass-through, granular state-dir mounts, and a two-tier network gateway."
author: "Hui Zhao (@0xSynapse, Heurion Research)"
date: "2026-11-05"
canonical_url: "https://heurion.org/en/blog/from-agent-plugins-to-enforced-runtime"
alternate_language_url: "https://heurion.org/blog/from-agent-plugins-to-enforced-runtime"
code_repository: "https://github.com/heurion-org/aegis-os"
paper_preprint: "https://github.com/heurion-org/aegis-os/blob/main/docs/AEGIS_ENFORCED_RUNTIME_DESIGN.md"
---

# Why Agent Plugins Are Not a Security Boundary: From Advisory Hooks to a Kernel-Enforced Agent Runtime

> **When an autonomous agent shares a privilege domain with its supervisor, hooks and system prompts are merely polite suggestions. This monograph details how Aegis OS lowers the enforcement boundary into the OS kernel via parent-process sandboxing, read-only .git pass-through, granular state-dir mounts, and a two-tier network gateway.**
>
> **Executive Summary**: Most contemporary AI coding and general-purpose agents (Claude Code, Codex, OpenCode, AGY, Hermes) rely on client plugins, PreToolUse hooks, MCP routing, and system prompts to govern tool execution. Under prompt injection or configuration drift, plugin-level governance fails as a security boundary due to uncovered native tools, shared daemon bypasses, self-modifying settings files, and direct host subprocess spawning. This monograph presents the Aegis OS Three-Tier Enforcement Architecture (Advisory / Enforced / Isolated): inverting control via the aegis-os run parent launcher, read-only .git index separation, single-file read-only config locking, a two-tier L4/L7 network gateway, and a generalized transactional commit pipeline across code, documents, datasets, and live applications.

## 01. Honest Threat Modeling: Why Agent Plugins & Hooks Are Advisory, Not Enforced

      
The most dangerous architectural illusion in AI agent infrastructure is **mistaking a workflow orchestration plugin for an operating system security boundary**. Modern terminal and IDE agents—including Claude Code, OpenCode, Codex CLI, Antigravity (AGY), and Hermes—typically expose three extension surfaces: system prompt instructions (`CLAUDE.md` / `AGENTS.md`), tool interception hooks (`PreToolUse` hooks and plugins), and Model Context Protocol (MCP) servers.

      
Under benign collaboration, plugin-based governance works remarkably well: hooks can transparently intercept native `Read`, `Edit`, and `Bash` calls and reroute them into an Aegis OS Copy-on-Write (CoW) shadow workspace. Yet the moment we inspect the process tree from the OS kernel’s perspective, an inescapable truth emerges: **in plugin mode, the agent main process itself runs directly inside the host user’s privilege domain, inheriting the human developer’s exact `UID`, `$HOME` visibility, and raw system call surface.**

      
> **The Kernel Boundary Axiom**: **No interceptor that executes within the same privilege domain as the supervised process—or relies on the supervised process to voluntarily invoke it—can ever be a security boundary.** Unless the agent process tree itself is confined inside an OS kernel sandbox (Linux Mount/PID/Network namespaces + Landlock/seccomp, macOS Seatbelt, or a microVM), hooks and MCP provide **Advisory Governance**, not **Enforced Isolation**.

      
During our end-to-end security audit across mainstream CLI and desktop agents, we cataloged **six structural bypass vectors** that plugin-only governance cannot eliminate:

      

        

          

            | Bypass Vector | Mechanism & Real-World Client Behavior | Why Hooks / Plugins Alone Cannot Fix It |

          

          

            | **1. Uncovered Native & 3rd-Party Tools** | Built-in tools like `NotebookEdit`, LSP refactoring actions, or project-injected `.mcp.json` servers (e.g., a raw `filesystem` MCP) | Hooks rely on denylisting known tool names; any newly added client tool or unknown MCP server mutates the host directly |

            | **2. Clients Without Tool-Level Hooks** | Clients such as Codex CLI support MCP servers and native sandboxing but do not currently expose an external `PreToolUse` interception hook | Routing relies entirely on soft prompt instructions in `AGENTS.md`, offering zero hard resistance against prompt injection |

            | **3. Shared Daemon Escape** | When OpenCode TUI connects via `--attach` to an already-running background server, plugin enforcement depends on the daemon’s startup state | A CLI wrapper cannot retroactively sandbox or inject plugins into a pre-existing host daemon process |

            | **4. Self-Modifying Config & Local Overrides** | An agent or build script modifies `~/.claude/settings.json`, `.claude/settings.local.json`, or `~/.config/opencode/opencode.json` | Because the agent has write access to its own config directory, it can strip its own hooks for subsequent turns or sessions |

            | **5. Host Side-Effects in "Read-Only" Commands** | Allowing seemingly benign commands like `git status`, `cargo test`, or `npm test` to run on the host workspace | `build.rs`, `postinstall` scripts, or `core.fsmonitor` in `.git/config` execute arbitrary host code and can read `~/.ssh` |

            | **6. Loopback Self-Approval** | A local subprocess sends an HTTP request to the local broker on `127.0.0.1` to approve its own pending escalation ticket | Without cryptographic separation between Agent Session Tokens and Human Admin Tokens, a same-UID process can forge approvals |

          

        

      

      
## 02. Three-Tier Enforcement (Advisory / Enforced / Isolated): Decoupling Ergonomics from Security

      
Acknowledging the limits of plugins does not mean abandoning them. In systems engineering, the two worst mistakes are breaking 95% of daily developer workflows with overly brittle defaults, or overclaiming security guarantees that do not hold under adversarial conditions. Aegis OS therefore defines **three explicit, verifiable Enforcement Tiers**, reported transparently in real time via `aegis-os status` and `aegis-os doctor`:

      
> **[Diagram]** Figure 1: The Aegis OS Three-Tier Enforcement Architecture (Advisory / Enforced / Isolated), separating productivity guardrails from kernel-enforced security boundaries.

      
## 03. Inverting Control: The `aegis-os run` Parent Launcher, Read-Only `.git` View & State-Dir Layering

      
Moving from Advisory to Enforced requires a single foundational shift: **inverting the parent-child process relationship. Instead of an agent living on the host and optionally calling Aegis, `aegis-os run -- <agent>` acts as the parent process—constructing a restricted kernel namespace first and spawning the agent binary inside it.**

      
Yet placing a full-featured modern CLI agent (such as Claude Code or OpenCode) inside a Linux `bubblewrap (bwrap)` + `Landlock` + `seccomp` or macOS `Seatbelt` sandbox immediately surfaces three practical systems challenges: (1) distro-specific dynamic linkers and package stores (NixOS, Linuxbrew, Snap) failing with `ENOENT`; (2) `git status` and `git diff` breaking or triggering malicious host Git hooks; and (3) the agent either losing its session history (`~/.claude/projects`) or retaining the ability to overwrite its own security settings (`~/.claude/settings.json`).

      
Aegis Enforced Runtime resolves all three without sacrificing security or developer ergonomics:

      
### 3.1 Distro-Compatible Root Masking (`--ro-bind / /`) & Path Remapping

      
Manually enumerating `/usr` and `/lib` breaks immediately on NixOS (`/nix/store`), Linuxbrew (`/home/linuxbrew/.linuxbrew`), and custom enterprise CA bundles. On Linux, Aegis preserves `--ro-bind / /` for universal binary compatibility, then immediately masks user and runtime state by mounting fresh `--tmpfs` over `/home`, `/root`, `/run`, `/var`, `/tmp`, `/mnt`, `/media`, and sensitive `/etc` credential files. Finally, it bind-mounts the **writable CoW shadow workspace directly onto the original host project path (`/home/user/project`)** while mounting the real host tree read-only at `/aegis/host/project`. Even if a prompt-injected agent bypasses every MCP tool and runs `python -c "open('src/lib.rs', 'w')"`, the kernel transparently redirects the write into the isolated CoW shadow.

      
### 3.2 Read-Only `.git` Object Pass-Through with `GIT_INDEX_FILE` Separation

      
Both developers and agents rely heavily on `git status`, `git diff`, `git log`, and prompt branch indicators. Stripping `.git` from the shadow breaks Git tooling; copying `.git` wastes hundreds of megabytes on large repositories; and exposing the host `.git` writable allows an agent to achieve host code execution by writing to `.git/hooks/pre-commit` or setting `core.fsmonitor` in `.git/config`.

      
Aegis OS solves this via a **Read-Only Object Store + Per-Session Writable Index + Hardened Git Shim**:

      
```
# 1. Bind-mount the host .git directory read-only into the shadow workspace
bwrap ... --ro-bind /aegis/host/project/.git /home/jz/project/.git

# 2. Copy only the single-file .git/index into the private session dir and redirect Git's index pointer
cp /aegis/host/project/.git/index ~/.aegis/sessions/$SESSION_ID/git-index
export GIT_INDEX_FILE="$HOME/.aegis-git-index"
export GIT_OPTIONAL_LOCKS=0
export GIT_CONFIG_NOSYSTEM=1
export GIT_CONFIG_GLOBAL=/dev/null

# 3. Prepend a Git safety shim that disables external diff/fsmonitor helpers and routes mutations to aos commit
git -c core.fsmonitor=false -c core.hooksPath=/dev/null status --no-ext-diff
```

      
This guarantees zero-copy `.git/objects` access and instant `git status` / `git diff` across 100k-file repositories while ensuring the host’s `.git/index` mtime is never touched and repository hooks can neither be modified nor executed.

      
### 3.3 Granular Agent State-Directory Layering (Single-File Read-Only Config Locks)

      
CLI agents must write conversation logs, todo lists, and OAuth refresh tokens at runtime (e.g., `~/.claude/projects/*.jsonl`, `~/.codex/sessions`, or OpenCode’s SQLite state in `~/.local/share/opencode`), but they must never be allowed to modify `~/.claude/settings.json`, `~/.gemini/config/hooks.json`, or `~/.codex/config.toml`. Leveraging ordered mount layering in `bwrap`, Aegis mounts state subdirectories writable first and then overlays **single-file `--ro-bind` locks onto every security-critical configuration file**—preserving full stateful session continuity while making self-modification of hooks and permissions kernel-impossible.

      
> **[Diagram]** Figure 2: Kernel mount topology and dual-mode network egress architecture under `aegis-os run`.

      
## 04. Effect-Driven Policy & Dual-Mode Egress: Separating CONNECT Tunnels from L7 Reverse Proxies

      
A pervasive anti-pattern in agent security is prompting the user to approve raw shell command strings. **Commands are not security primitives; Effects are.** Running `cargo test` reads and writes hundreds of files inside the build directory, yet as long as those effects are confined to the disposable CoW shadow workspace and read-only toolchains, the user should never be interrupted. Conversely, a single file write that touches `.github/workflows/release.yml` or `build.rs` represents a high-risk persistence vector when committed back to the host.

      
Aegis OS models every operation as a structured `(EffectKind, ResourceScope, Reversibility)` tuple evaluated by our Cedar policy engine. Reversible mutations inside the shadow workspace are auto-allowed with automatic snapshots; irreversible boundary transitions (`workspace.commit`, `workspace.commit_sensitive`, out-of-workspace reads, or unallowlisted network egress) require a capability lease or human approval.

      
For network egress inside `--unshare-net`, we also reject the dishonest industry claim that a standard HTTPS `CONNECT` proxy provides L7 Data Loss Prevention (DLP). Because `CONNECT` establishes an end-to-end encrypted TLS tunnel, the proxy only observes `host:port` and byte counts—never the HTTP method, path, or request body. Aegis OS therefore separates egress into explicit modes:

      

        - **Mode 1: L4 `CONNECT` Tunnel (Default for package managers & general HTTPS)** — Evaluates `net.connect` against domain/port allowlists with zero streaming latency and zero TLS certificate breakage, without fabricating L7 method logs.

        - **Mode 2: L7 `Base URL` Reverse Proxy (Default for LLM & SaaS APIs)** — The launcher points `ANTHROPIC_BASE_URL` / `OPENAI_BASE_URL` to a local gateway. The gateway inspects full L7 `net.request` methods and paths, scans request bodies for PHI/secrets before forwarding, **injects API keys at the boundary so raw credentials never enter the sandbox environment**, and streams SSE responses without buffering time-to-first-token.

        - **Mode 3: Opt-in MITM (Explicit enterprise domains only)** — Issues a per-session CA strictly for domains listed in `mitm_domains`, failing closed or visibly downgrading if a binary uses hardcoded certificate pinning.

      

      
## 05. Generalized Domain Commit Pipelines & Non-Destructive TUI Approvals

      
Autonomous agents are no longer confined to software repositories; they author research manuscripts (`Documents`), clean clinical cohorts (`Data`), generate figures (`Binary`), and mutate live enterprise software (`AppState`). A runtime that only understands `git diff` leaves non-code workflows completely unprotected.

      
Aegis Enforced Runtime generalizes the **`shadow → verify → approve → land`** transaction pipeline across domains via declarative `DomainProfile` configurations:

      

        - **Code & Documents**: 4-tier LCS 3-way auto-merge with sandboxed pre-flight verification gates (`cargo test`, `latexmk -pdf`, citation & link checks), pairing in Phase 5 with Heurion’s Dual-Surface CRDT block locks and `patchParagraph` byte-preserving OOXML splicer for Word/PowerPoint archives.

        - **Binary Assets (Figures, PDFs, Medical Imaging)**: Because binary files cannot be merged line-by-line, Aegis enforces exclusive `coord_claim` locks and records a **baseline SHA-256 hash** at shadow creation—requiring explicit `overwrite_binaries` approval with before/after hash evidence prior to landing on the host.

        - **Data & Content-Addressed Pipelines (Org CAS)**: Upstream data agents must pass schema validation and `scanPhi --strict` inside the sandbox before publishing immutable SHA-256 artifacts via `org_artifact_publish`, structurally preventing downstream agents from reading half-written files.

      

      
> **Respecting Terminal Physics: Never Write Raw Approval Prompts into an Active Full-Screen TUI**: When Claude Code, OpenCode, or Codex is rendering a full-screen Alternate Screen TUI in raw mode, having a parent supervisor write approval text directly to the shared PTY’s `stderr`—or compete for `stdin` keystrokes—instantly corrupts the terminal layout and deadlocks input. When a full-screen TUI is active, Aegis OS **never writes raw approval text into the main screen**: instead, it notifies the human out-of-band via desktop notifications, terminal `OSC 0` title bar badges (`⏳ Aegis: 1 approval pending`), a companion `aegis-os approve` CLI in a second terminal, or the SHA-256 diff-locked local Web console (with an optional 1-line `DECSTBM` scroll-region status bar for headless SSH). Only when kernel security respects terminal physics will developers keep enforcement enabled by default.

## Frequently Asked Questions (Technical FAQ)

### Q: Why can’t agent plugins (PreToolUse hooks + MCP servers) serve as a true security boundary?
Because plugins and hooks execute inside the same host user privilege domain (same UID, filesystem view, and syscall surface) as the supervised agent. Under prompt injection or configuration drift, an agent can invoke uncovered native tools (e.g., NotebookEdit), attach to an unsandboxed background daemon (OpenCode --attach), overwrite its own ~/.claude/settings.json to strip hooks, or trigger host code execution via build.rs or .git/config fsmonitor during seemingly benign commands. Plugins provide Advisory ergonomics; true Enforced isolation requires aegis-os run to act as the parent process and confine the entire agent tree inside an OS kernel sandbox.

### Q: How does aegis-os run keep git status and stateful agent sessions working without letting the agent tamper with .git or its own security settings?
Through two layered mount mechanisms: (1) It bind-mounts the host .git directory read-only into the shadow workspace for zero-copy object access, copies only the single-file .git/index into a private session path pointed to by GIT_INDEX_FILE, and injects a hardened Git shim that disables core.fsmonitor and hooksPath; (2) It mounts runtime state directories (~/.claude/projects, ~/.codex/sessions, ~/.local/share/opencode) writable first, then overlays single-file read-only mounts (--ro-bind) onto ~/.claude/settings.json, ~/.gemini/config/hooks.json, and ~/.codex/config.toml so the agent cannot disarm its own supervision.

### Q: Why does Aegis OS separate L4 HTTPS CONNECT tunnels from L7 Base URL reverse proxies?
A standard HTTPS CONNECT proxy only sees host:port over an encrypted TLS tunnel—it cannot inspect HTTP methods, URL paths, or request bodies without breaking TLS via MITM. Aegis OS therefore uses a dual-mode gateway: general HTTPS traffic uses an L4 CONNECT tunnel (enforcing net.connect domain/port allowlists with zero streaming overhead and intact certificate pinning), while LLM and SaaS APIs use an L7 Base URL reverse proxy (via ANTHROPIC_BASE_URL / OPENAI_BASE_URL) that performs net.request method auditing, boundary API key injection (keeping raw keys out of the sandbox), and request-body DLP without buffering streaming SSE tokens.
