Crust: The HTTP Proxy That Stops AI Agents from Deleting Your Production Database
Hook
When GitHub Copilot Workspace or AutoGPT asks an LLM to execute rm -rf /, the only thing standing between your filesystem and oblivion is a JSON object flying over HTTP. What if you could intercept that moment?
Context
AI agents are graduating from parlor tricks to production workflows. Tools like LangChain, AutoGPT, and Claude’s computer use API now routinely grant LLMs the ability to execute shell commands, manipulate files, and call APIs on your behalf. The promise is extraordinary: autonomous coding assistants that refactor entire codebases, research agents that browse documentation and generate reports, DevOps bots that diagnose and fix infrastructure issues.
But there’s a darker side to this capability explosion. In late 2023, security researchers demonstrated prompt injection attacks where carefully crafted inputs could trick agents into exfiltrating SSH keys, establishing persistence mechanisms, or wiping directories. The fundamental problem is architectural: most agent frameworks execute tool calls immediately after the LLM generates them, with no intermediate safety checks. Traditional security tooling—firewalls, runtime sandboxes, static analysis—either lacks visibility into agent semantics or requires heavyweight integration. Crust emerged from this gap: a lightweight, transparent proxy that sits between agents and LLMs, inspecting tool calls at the exact moment they transition from “language” to “action.”
Technical Insight
Crust’s architecture is deceptively simple: it’s an HTTP proxy written in Go that masquerades as your LLM provider’s API endpoint. Instead of pointing your agent at https://api.openai.com/v1/chat/completions, you point it at http://localhost:8090/v1/chat/completions. Crust forwards the request upstream, but not before scanning it for dangerous patterns.
The genius is in the two-layer interception model. Layer 0 scans the conversation history in the incoming request—this catches cases where the agent itself has already decided to do something dangerous and is asking the LLM for confirmation or refinement. Layer 1 scans the LLM’s response for tool calls before returning it to the agent. This dual approach means you catch threats both from compromised agent logic and from the LLM generating novel dangerous actions.
Here’s what integration looks like in practice. Suppose you’re running an AutoGPT instance:
# Before: Direct LLM access
import openai
openai.api_base = "https://api.openai.com/v1"
openai.api_key = "sk-..."
# After: Route through Crust
import openai
openai.api_base = "http://localhost:8090/v1"
openai.api_key = "sk-..." # Still your real key; Crust forwards it
That’s it. No SDK modifications, no framework-specific plugins. Because Crust speaks the OpenAI-compatible API format (which has become the de facto standard), it works with LangChain, Haystack, Semantic Kernel, or any custom agent code.
The rule engine is where things get interesting. Crust uses a YAML-based policy format that combines glob patterns for tool name matching with regex for argument inspection:
rules:
- name: block_recursive_delete
tool_name_pattern: "execute_shell"
argument_pattern: ".*rm\\s+-rf\\s+/.*"
action: block
severity: critical
message: "Recursive root deletion attempt blocked"
- name: detect_ssh_key_access
tool_name_pattern: "read_file"
argument_pattern: ".*/\\.ssh/(id_rsa|id_ed25519)$"
action: alert
severity: high
message: "SSH private key access detected"
When a rule triggers with action: block, Crust returns an error to the agent before the tool call executes. With action: alert, it logs the event but allows execution—useful for building behavioral baselines without breaking workflows. The regex engine uses Go’s regexp package, which is fast but lacks some Perl-compatible features like lookbehind assertions (a reasonable tradeoff for performance).
Crust supports two operational modes. Manual mode requires you to specify a single upstream provider explicitly—useful when you control the LLM endpoint. Auto mode is more ambitious: it inspects the model field in requests (e.g., gpt-4, claude-3-opus) and automatically routes to the appropriate provider. This enables a fascinating use case: multi-LLM agents where different reasoning steps use different models, all protected by a single Crust instance. The implementation maintains a provider registry that maps model name prefixes to API endpoints:
// Simplified from actual codebase
type ProviderRegistry struct {
providers map[string]Provider
}
func (r *ProviderRegistry) ResolveProvider(modelName string) (Provider, error) {
for prefix, provider := range r.providers {
if strings.HasPrefix(modelName, prefix) {
return provider, nil
}
}
return nil, ErrProviderNotFound
}
One architectural detail worth highlighting: Crust stores all telemetry locally in encrypted SQLite databases. This isn’t just about privacy—it’s about trust. Many security tools become liability vectors themselves when they centralize sensitive data. By keeping everything local and encrypted at rest, Crust ensures that your agent’s conversations (which may contain proprietary code, credentials, or strategic discussions) never leave your infrastructure. The roadmap includes advanced analysis features, but the current “review-only” model means you’re manually inspecting logs rather than getting automated threat intelligence.
The hot-reload capability deserves mention too. Rules are watched via filesystem notifications; when you edit the YAML file, Crust reloads policies without dropping connections. This is critical during incident response—if you discover a new attack pattern, you can deploy a blocking rule in seconds without restarting the proxy or disrupting running agents.
Gotcha
The most significant limitation is right there in the documentation: auto mode is marked experimental. In practice, this means edge cases in model name resolution (what happens with custom fine-tuned models like gpt-4-mycompany-v2?) and potential stability issues under high concurrency when routing to multiple providers. If you’re building something production-critical, manual mode with a single upstream is the safer bet.
More fundamentally, rule-based filtering has inherent blind spots. Sophisticated prompt injection can disguise malicious intent in ways that evade regex patterns. For example, an attacker might exploit Unicode homoglyphs, encoding tricks, or chain multiple innocuous-looking tool calls that become dangerous in combination. A rule blocking rm -rf / won’t catch an agent that first writes a malicious script to /tmp/cleanup.sh and then executes it. Crust provides a valuable security layer, but it’s not a silver bullet—it’s most effective as part of a defense-in-depth strategy alongside sandboxing, least-privilege access controls, and input validation.
Finally, the telemetry system is currently primitive. You get logs of blocked actions, but no anomaly detection, no baselines of “normal” agent behavior, no correlation of patterns across multiple agents. The roadmap promises advanced scanning, but today you’re manually grepping through SQLite databases if you want to do forensics. For research or small deployments this is fine; for enterprise environments managing dozens of agents, you’ll need to build additional tooling.
Verdict
Use Crust if: You’re deploying AI agents with filesystem or shell access and need a practical safety net today—especially in development environments, autonomous coding assistants, or agent safety research. The zero-code integration means you can add protection to existing workflows in under five minutes, and the latency overhead (typically <10ms for rule evaluation) is negligible for most use cases. It’s also excellent for learning about agent attack surfaces; just running Crust with verbose logging will surface surprising behaviors in how your agents actually use tools. Skip it if: You need enterprise-grade security with guaranteed protection against sophisticated attacks (rule engines can be evaded), you’re working with agents already running in strong sandboxes (Docker with minimal capabilities, gVisor, etc.) where the blast radius is already contained, or you require mature features like centralized policy management across distributed deployments and real-time threat intelligence. Also skip if you’re using non-standard LLM APIs that don’t follow OpenAI’s format—Crust won’t understand the protocol. Think of Crust as the seatbelt in your agent deployment: not sufficient for crash survivability on its own, but stupid to drive without.