Kernel ring — OS sandbox rules
Kernel ring — OS sandbox rules
Section titled “Kernel ring — OS sandbox rules”What it does: Applies network egress allowlist + Landlock filesystem rules + credential hiding to the agent's process; the deepest enforcement layer.
1. Vision context
Section titled “1. Vision context”This is the layer attackers cannot bypass by patching userspace. Every other layer (gateway, MCP, codemode, harness) operates inside the agent's process; if any are compromised, the kernel is the last line of defense.
The kernel layer answers a single question: "can this process reach this address / read this file?" Even an LLM that perfectly hallucinates a forbidden tool call, or agent code that bypasses every userspace check, hits a network egress that physically cannot reach the destination.
This layer reuses TapPass's existing OpenShell sandbox (tappass/sandbox/) — Landlock for filesystem, L7 network policy via inference.local, credential hiding. What's new is the applier that takes the keyring's layer-1 slice and expresses it as OpenShell config at sandbox start (and re-applies on sync push).
See concepts/governed-agents-architecture.md §6 (defense in depth) and §9 (enforcement layers) for full context.
2. Functional specification
Section titled “2. Functional specification”Inputs: the layer-1 slice of a SandboxConfig:
layer_1_kernel: network_egress_allowlist: - "*.tappass.ai" - "api.tappass.ai" fs_read_allowlist: - "/var/run/tappass/<sandbox_id>/keyring.json" - "/var/run/tappass/<sandbox_id>/agent-data/" fs_write_allowlist: - "/var/run/tappass/<sandbox_id>/agent-data/" landlock_rules: - {path: "/etc", access: ro} - {path: "/proc", access: ro} credential_hiding: enabled: true hidden_env_vars: [OPENAI_API_KEY, ANTHROPIC_API_KEY]Outputs: an active sandbox namespace with the rules applied. Returns success/failure to host-runtime-cli.
Error cases:
- Landlock unavailable (non-Linux host) → emit warning, mark this layer as
unavailablein audit, continue with reduced defense - Network namespace creation fails → fail sandbox start; the agent process must not run with reduced kernel-layer enforcement under enforced policies
- Apply during running sandbox (sync push) — narrow window: drain in-flight egress, swap rules atomically, resume
Non-goals:
- Choosing what to allow/deny (that's the policy-to-sandbox-config-builder)
- Per-call enforcement (that's the gateway/MCP layers)
- Crash recovery if OpenShell daemon dies (that's the host runtime CLI's responsibility)
3. Technical design
Section titled “3. Technical design”Where it lives: tappass-host/src/layers/kernel.py. Imports OpenShell primitives from tappass/sandbox/.
At sandbox start:
- Read
layer_1_kernelfrom the mounted keyring file. - Create a Linux network namespace; configure
iptables/nftablesegress rules fromnetwork_egress_allowlist. - Apply Landlock filesystem rules via
landlocksyscall (or libsandbox wrapper). - Start the credential-hiding proxy (
inference.local) inside the namespace. - Hand control to layer-2 applier (the agent process exec happens at the end of all layer applies).
On sync push:
- Re-read layer-1 slice.
- Diff against currently applied rules.
- Apply diff atomically (swap egress rule sets via netfilter; Landlock is more restrictive — may require sandbox restart for certain rule expansions, never for restrictions).
Integration points:
- Reads keyring file via shared mount.
- Coordinates with layer-2/3 appliers via the host runtime CLI's layer-application sequence.
- Emits audit events:
kernel_layer_applied,kernel_layer_unavailable,kernel_layer_apply_failed,egress_denied_by_kernel.
4. Definition of done
Section titled “4. Definition of done”- All
acceptance_criteriapass. - Integration test: sandbox started with
egress_allowlist: [tappass.ai];curl https://collibra.comfrom inside the sandbox fails with network unreachable. - Integration test: sandbox started with Landlock rules;
cat /etc/passwdallowed,cat /etc/shadowdenied. - Integration test: sync push that narrows the allowlist; in-flight call to a now-denied destination fails on next attempt.
- Audit events fire correctly for all paths (apply, fail, unavailable).
- macOS / Windows graceful degradation tested.
- Spec doc section in
concepts/tappass-keyring-and-sync.mdwritten.
5. Coordination notes
Section titled “5. Coordination notes”With host-runtime-cli: the host CLI invokes our apply() function at sandbox start and on every keyring change. We expose a single entry point: apply(layer_config: dict, sandbox_id: str) -> ApplyResult.
With ring-harness, ring-interpreter: we run first in the sequence (kernel → codemode → harness → mcp → gateway). Subsequent layers depend on us having created the namespace and applied egress.
With policy-to-sandbox-config-builder: we consume layer_1_kernel from its output. The builder owns the schema; we own the applier.
Open questions:
- (Q) Should the egress allowlist support per-tool destinations (e.g., when a tool catalog entry adds
acme-internal.comto the universe)? Lean: yes;tools_destinationsfield added to the layer-1 config, merged with global allowlist. Owner: this component. - (Q) What happens if Landlock kernel version doesn't support a rule we want to apply? Lean: drop the rule with audit warning, continue with the rest. Owner: this component.
6. Out of scope
Section titled “6. Out of scope”- Choosing what to allow/deny → see policy-to-sandbox-config-builder
- Cross-namespace isolation between sandboxes (already handled by the kernel — each sandbox is a separate namespace; we don't manage that at this layer)
- macOS/Windows replacement for Landlock — out of scope for v1; the
--layers kernelflag will be ignored on those platforms with audit warning - Container security (cgroup limits, seccomp profiles) → may belong here in v2; for v1, scoped to network + filesystem + credentials