SCARAB RUNTIME
Hardened execution layer for autonomous AI agents.
Isolation via seccomp-BPF,
AppArmor,
cgroups, and
nftables —
zero-trust from the kernel up.
Hardened
Syscall filtering via seccomp-BPF. AppArmor confinement profiles auto-generated from agent manifests.
Isolated
OverlayFS workspaces with snapshot/rollback. Cgroups v2 hard limits on memory, CPU, and PID exhaustion.
Verifiable
SHA-256 hash-chained NDJSON audit logs. Append-only. Tamper-resistant. Every tool call recorded.
Isolation
Architecture
Seccomp-BPF
A BPF program compiled and loaded into the kernel at agent spawn time. Enforces a strict syscall allowlist derived from the agent's trust level. Any unlisted syscall terminates the process immediately with SIGSYS — no fallback, no escalation.
AppArmor
Mandatory Access Control profiles auto-generated from the agent's capability manifest at spawn. Restricts filesystem path access, Linux capability bits, and socket operations. Enforced via kernel LSM hooks — no userspace path can bypass confinement.
Cgroups v2
Hard resource ceilings enforced by the kernel controller hierarchy. Memory (hard + swap), CPU quota (burst and sustained windows), PID count, and I/O throttle rates. Prevents resource exhaustion, fork bombs, and noisy-neighbour attacks between concurrent agents.
Nftables
Per-agent network namespaces backed by nftables rules. Four escalating network policies specified in the manifest: none (air-gapped), local-only, allowlist (explicit domain list), and full. Default policy is none — agents have no network access unless explicitly granted.
Prompt injection into external data cannot be stopped at the LLM level — once tainted content enters the context window, all subsequent reasoning is potentially compromised. Scarab tracks which agents have read external data and blocks them from calling output tools at dispatch time. No LLM reasoning is trusted for any security-relevant action.
Tool Categories
Every tool registered in agentd carries a static category and per-tool tainting and sensitive flags. These drive taint propagation and the exfiltration gate at dispatch — independently of anything the LLM produces.
Exfiltration Gate
Each tool carries independent tainting and sensitive flags. A tool call taints the agent if it reads external data; it marks the agent sensitive if it handles data that must not leave. The exfiltration gate fires only when both flags are set — blocking Output-category tools on agents that have seen sensitive data and are potentially compromised by injection.
InjectionPolicy
Content returned by Input-category tools is wrapped in <external_content> delimiters before entering the LLM context, signalling to the model that the enclosed text is untrusted. An optional second classifier model call can validate the prompt before it reaches the primary LLM.
Reading any data.* key permanently taints the reading agent. At dispatch, agentd blocks agents that hold the agent.spawn capability from reading these keys — orchestrators coordinate without ever seeing raw external data.
Reading control.* keys does not taint. Writes to control.* are validated at dispatch against a JSON Schema declared in the writing agent's manifest (spec.control_schema), limiting the injection surface to the declared schema shape.
OverlayFS Workspaces
Each agent receives a private OverlayFS workspace at spawn — an isolated view of the filesystem backed by copy-on-write semantics. The lower layer is read-only; all writes are captured in an agent-specific upper layer.
Capability Tokens
Every tool invocation is gated by an unforgeable capability token in domain.action:scope format. Tokens are issued at spawn from the agent manifest and validated by agentd on every dispatch. Agents cannot escalate or mint new tokens.
Secret Store
Agents never hold raw secrets. Credentials are injected as opaque handles ({{secret:name}}) and substituted inside the agentd dispatch layer — then scrubbed before results re-enter LLM context.
Immutable Log
Every tool call, phase transition, and credential access is written to an append-only NDJSON log. Each entry is chained via SHA-256 to the previous — making retroactive tampering detectable.
Watchdog
A continuous watchdog monitors the audit trail in real time. Anomalous patterns trigger escalation up the agent hierarchy — or immediate termination.
REST API
agentd-api exposes the full agent lifecycle over HTTP. Bearer token auth, SSE live event stream, and JSON everywhere. Runs on port 8080 by default.
curl -X POST \
https://scarab.local:8080/api/v1/agents \
-H "Authorization: Bearer $SCARAB_TOKEN" \
-H "Content-Type: application/json" \
-d '{"manifest":"etc/agents/example-agent.yaml","trust_level":"sandboxed"}' {
"agent_id": "agent:example-01",
"status": "spawning",
"workspace": "/var/scarab/ws/a1b2c3",
"trust_level": "sandboxed",
"created_at": "2025-01-15T09:00:00Z"
} Agent SDK
Build autonomous agents that run inside Scarab's execution environment. The libagent SDK handles IPC, capability enforcement, and the plan→act→observe loop.
use libagent::{Agent, ToolResult};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Initialize from SCARAB_* environment vars
let mut agent = Agent::from_env()?;
loop {
// Plan: determine next action
let action = agent.plan().await?;
if action.is_terminal() { break; }
// Act: invoke sandboxed tool via agentd
let result: ToolResult =
agent.invoke(&action).await?;
// Observe: update context with result
agent.observe(result).await?;
}
agent.complete().await
} [dependencies]
libagent = { path = "../libagent" }
tokio = { version = "1", features = ["full"] }
anyhow = "1" Ready to isolate your agents?
Scarab is MIT-licensed and runs on any Linux 5.x+ system. Pull the repo and spawn your first agent in minutes.