How OmniRoute's Guardrail System Prevents Prompt Injection and Credential Leakage
OmniRoute's guardrail system uses a hot-reloadable registry with preCall and postCall hooks to scan, redact, or block malicious content before it reaches upstream LLM providers.
The open-source OmniRoute project (diegosouzapw/OmniRoute) implements a layered defense architecture that intercepts every inbound request and outbound response. Its guardrail system combines pattern-based detection, configurable severity thresholds, and flexible deployment modes to stop prompt injection attacks and credential leakage without requiring code changes.
The Guardrail Registry: Core Architecture
At the heart of the system sits the guardrail registry (src/lib/guardrails/registry.ts). This module orchestrates a chain of guardrails that execute in priority order on every request/response cycle.
Each guardrail implements a standard interface with two lifecycle hooks:
preCall: Executes before the provider receives the requestpostCall: Executes after the provider returns a response
The registry is fail-open by design—if a guardrail throws an exception, the error is logged and processing continues to the next guardrail. Traffic only blocks when a guardrail explicitly returns a block decision based on its own logic.
Guardrails can be globally enabled or disabled via environment variables, or overridden per-request using the x-omniroute-disabled-guardrails HTTP header.
Prompt Injection Prevention
The prompt injection guardrail (src/lib/guardrails/promptInjection.ts) protects upstream LLMs from malicious system prompt overrides and hidden instruction attacks.
Detection Components
| Component | Implementation |
|---|---|
| Pattern catalog | Built-in DEFAULT_GUARD_PATTERNS with regexes like /system\s*:\s*override/i and markdown-embedded system prompt detection |
| Custom patterns | User-defined regexes passed via customPatterns option |
| Severity scoring | low, medium, or high classification per detection |
| Block threshold | Configurable blockThreshold determines when rejection occurs |
| Operational modes | "block" (reject), "warn" (log high-severity only), "log" (always log) |
Execution Flow
The guardrail Processes requests through four stages:
- Sanitization: The payload runs through
sanitizeRequestfor baseline injection detection - Pattern scanning: The first 16KB of concatenated message contents (
MAX_INJECTION_SCAN_BYTES) is scanned against custom patterns - Result merging: New detections merge with the sanitizer's findings
- Decision: If mode is
"block"and accumulated severity exceedsblockThreshold, returns{ block: true, message: "Request rejected: suspicious content detected" }; otherwise returns metadata describing detection counts
The default mode is "warn", overrideable via the INJECTION_GUARD_MODE feature flag using the precedence: database value > environment variable > default.
Credential Leakage Prevention
The credential masker guardrail (src/lib/guardrails/credentialMasker.ts) prevents accidental API key and secret token exposure to third-party LLM providers.
Key Mechanisms
| Feature | Description |
|---|---|
| Feature flag | CREDENTIAL_REDACTION_ENABLED controls activation (DB > env > default) |
| Pattern matching | Detects patterns like AWS keys (AKIA[0-9A-Z]{16}) and generic secrets ((?i)(secret|key)[\s:=]+[A-Za-z0-9+/=]{20,}) |
| Redaction | Matching substrings replaced with "⛔️[REDACTED]" |
| Metadata tracking | Records redaction count in the payload meta |
Hook Behavior
- Pre-call: Returns
modifiedPayloadwith redacted content—the provider never receives raw credentials - Post-call: Non-blocking; only records that redaction occurred
When disabled, the guardrail becomes a no-op with minimal performance overhead.
Complementary PII Protection
The PII masker guardrail (src/lib/guardrails/piiMasker.ts) extends protection to personally identifiable information. Enabled via PII_REDACTION_ENABLED, it traverses JSON payloads and applies processPII to every string value in both requests and responses.
End-to-End Request Flow
1. Incoming request
└── guardrailRegistry.runPreCallHooks(payload, ctx)
├── credentialMasker (priority: highest)
├── piiMasker
└── promptInjection (priority: lowest)
↓
2. If blocked → return 4xx error
If passed → send modifiedPayload to provider
↓
3. Response received
└── guardrailRegistry.runPostCallHooks(response, ctx)
└── piiMasker (optional response redaction)
The /api/guardrails and /api/guardrails/test endpoints provide runtime observability into guardrail status and behavior.
Practical Configuration Examples
Per-Request Guardrail Disabling
For trusted internal services that need to send system prompts:
import { fetch } from "node-fetch";
await fetch("https://omniroute.example.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-omniroute-disabled-guardrails": "prompt-injection",
},
body: JSON.stringify({
model: "gpt-4o",
messages: [{ role: "system", content: "You are a helpful assistant." }],
}),
});
Environment-Based Configuration
# Enable strict prompt injection blocking
export INJECTION_GUARD_MODE=block
# Enable credential redaction
export CREDENTIAL_REDACTION_ENABLED=true
# Enable PII masking
export PII_REDACTION_ENABLED=true
Source File Reference
| File | Purpose |
|---|---|
src/lib/guardrails/base.ts |
Abstract base class defining the guardrail interface |
src/lib/guardrails/registry.ts |
Orchestrates guardrail execution order and hook invocation |
src/lib/guardrails/promptInjection.ts |
Prompt injection detection (lines 49-85, 92-120, 162-184, 210-227, 248-267) |
src/lib/guardrails/credentialMasker.ts |
API key and secret token redaction |
src/lib/guardrails/piiMasker.ts |
Personal data identification and removal |
docs/security/GUARDRAILS.md |
Architecture and configuration documentation |
Summary
- Hot-reloadable registry (
src/lib/guardrails/registry.ts) chains guardrails withpreCallandpostCallhooks - Fail-open design logs errors but continues processing unless explicit block returned
- Prompt injection guardrail uses
DEFAULT_GUARD_PATTERNS, severity scoring, and configurableblockThresholdwithINJECTION_GUARD_MODEcontrol - Credential masker redacts secrets via
CREDENTIAL_REDACTION_ENABLEDbefore provider handoff - Per-request overrides supported via
x-omniroute-disabled-guardrailsheader - Observable runtime through dedicated API endpoints
Frequently Asked Questions
What happens if a guardrail throws an exception?
The registry catches the error, logs it, and continues to the next guardrail. The system prioritizes availability over strict enforcement unless a guardrail explicitly returns a block decision.
Can I disable guardrails for specific requests only?
Yes. Pass the x-omniroute-disabled-guardrails header with a comma-separated list of guardrail names to disable. This is useful for trusted internal services that need to send system prompts or handle pre-validated data.
How does the prompt injection guardrail handle large payloads?
It limits scanning to the first 16KB of concatenated message contents (MAX_INJECTION_SCAN_BYTES). This balances security coverage with performance, as injection attempts typically appear in early message content.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →