Ship LLM features without shipping your users' secrets.
Your model will be handed PII it shouldn't keep, fed API keys pasted into a prompt, and probed with jailbreaks. cerberust is the fast layer that sits between your app and the model and stops it — redacting personal data, masking secrets so they never reach a provider, and blocking prompt injection before a single token is generated.
It's a Rust answer to Python's
llm-guard: the same idea — composable
scanners you stack in front of a model — built to run compiled, allocation-light,
and streaming-safe, with a regex engine that can't be tripped into
catastrophic backtracking.
cerberust began as the guardrail layer for gm — confidential, TEE-sealed LLM inference — and is developed in the open as a standalone library.
- Fast. The deterministic scanners run compiled Rust over regex automata — one to four orders of magnitude faster than a Python guardrail stack on the same corpus (benchmarks).
- Streaming-safe by design. A secret split across two streamed chunks is never half-emitted. The runner holds back exactly the bytes that could still be completing a match, and nothing more.
- Redaction with restore. PII is tokenized on the way in and put back on the way out — your user still reads their own email address in the reply, but the model never saw it. Secrets get the same treatment and are never restored.
- Cache-stable placeholders, optionally. By default each request mints a fresh random nonce, so the same value redacts differently every time. Opt into deterministic mode and a value's placeholder becomes a keyed function of the value — byte-identical across requests — so a replayed conversation prefix redacts the same way turn after turn and stays friendly to a provider's prompt cache (deterministic redaction).
- Composable. Scanners are pure
text -> verdictfunctions. Stack them in any order; the stack threads the rewritten text and a shared vault through every one. - Extensible and sandboxed. Bring your own patterns with a custom regex scanner, or write a guard in any language, compile it to WebAssembly, and run it with no filesystem, network, or clock — it physically cannot exfiltrate the text it inspects.
- No surprises. No catastrophic backtracking (linear-time matching, guaranteed), no secrets leaking through error paths, request-scoped state zeroized on drop.
[dependencies]
cerberust = "0.1"use cerberust::{
GuardrailRunner, MiddlewareChain, Params, PiiScanner, RestoreScanner,
Scanner, ScannerStack, SecretScanner,
};
// Build a stack: redact PII, mask secrets, restore PII on the way back.
let scanners: Vec<Box<dyn Scanner>> = vec![
Box::new(PiiScanner::new()), // email/phone/card/IP/SSN/IBAN -> tokenized
Box::new(SecretScanner::new()), // API keys/secrets -> masked, one-way
Box::new(RestoreScanner::for_pii()), // PII rehydrated in the response
];
let runner = GuardrailRunner::new("guard", ScannerStack::new(scanners, true));
let chain = MiddlewareChain::new(vec![&runner]);
// chain.generate(Params::new("email alice@example.com, key AKIA…"), &model)
// -> the model sees redacted text; the email comes back in the reply,
// the secret never does.&model is anything implementing the Model trait — point it at your existing
client. See Getting started for the full loop,
including streaming.
cerberust is pass-through by default. Nothing runs until you add it to a
ScannerStack, so every scanner is opt-in by construction — you compose exactly the
ones you want. The mode below is what each does once you include it.
(PromptInjectionScanner and WasmScanner additionally sit behind off-by-default
cargo features, since they pull heavy dependencies.)
| Scanner | Protects you from | Mode when added |
|---|---|---|
PiiScanner |
leaking emails, phone numbers, credit cards, IPs, SSNs, and IBANs to a model provider | redact (round-trip — restore in the reply) |
SecretScanner |
API keys, tokens, and private keys pasted into a prompt reaching a provider or being echoed back | redact, one-way (never restored) |
RegexScanner |
your own sensitive formats — ticket ids, account numbers, internal tokens | redact your patterns |
BanSubstringsScanner |
specific phrases you never want in a prompt or a reply | block on match |
BanTopicsScanner |
whole subjects you've ruled out, defined by keywords | block on match |
TokenLimitScanner |
oversized prompts blowing your context budget or your bill | block when over the limit |
RestoreScanner |
— (the output half that puts redacted PII back in the reply) | restores a round-trip scanner |
PromptInjectionScanner |
jailbreaks and "ignore your instructions" attacks | block · needs prompt-injection feature |
WasmScanner |
running an untrusted custom guard safely (sandboxed, no egress) | runs your guard · needs wasm feature |
A guardrail's job is to not corrupt the prompt your user paid for — so cerberust
optimizes for precision (deterministic regex + checksums), not the recall of a
fuzzy NER model that over-redacts ordinary words. Measured against llm-guard on a
shared 290-sample corpus (Apple Silicon), comparing only like-for-like:
Same detector, faster runtime — same patterns / same model, so it's a fair race:
| Scanner | cerberust | llm-guard | result |
|---|---|---|---|
| Regex (same patterns) | 7.81M/s | 124.5k/s | ~63× faster, identical detection |
| Ban-substrings (same phrases) | 1.16M/s | 135.5k/s | ~9× faster, identical detection |
| Prompt-injection (same model) | 126/s | 96/s | tie — byte-identical detection |
PII & Secrets — a different approach, on purpose. cerberust's deterministic
detectors run at >1.3M/s with perfect precision/recall on structured entities,
and don't over-redact — where llm-guard's NER scores 0.75 / 0.89. It's regex vs a
neural net, so we don't headline a speed multiple; NER leads on free-text names
cerberust deliberately doesn't attempt. Full methodology + honest caveats:
docs/benchmarks.md.
[dependencies]
cerberust = "0.1"Two heavy capabilities are off by default so the core stays lean:
# ML prompt-injection (pulls ONNX Runtime + a tokenizer; downloads a ~739 MB model)
cerberust = { version = "0.1", features = ["prompt-injection"] }
# Sandboxed WASM guards (pulls the wasmtime runtime)
cerberust = { version = "0.1", features = ["wasm"] }- Introduction & threat model
- Getting started
- Core concepts — scanners, the stack, middleware, the vault, streaming
- Scanner reference — one page per scanner
- Benchmarks
cerberust is the open-source guardrail library from gm — confidential LLM inference on Bittensor. Point your existing OpenAI, Anthropic, or Gemini SDK at the gm gateway and get identical behavior, sealed inside an Intel TDX enclave so no operator or host ever sees your prompts.
Licensed under either of MIT or Apache-2.0 at your option.
cerberust ports the scanner-and-stack design pioneered by
llm-guard (Protect AI) to Rust. The
threat model, the scanner lineup, and the prompt-injection model are its
inspiration — with gratitude.