How to Implement Guardrails in OmniRoute: PII Redaction, Prompt Injection Detection, and Vision Safety
OmniRoute provides a modular guardrail framework that intercepts LLM requests and responses to enforce PII redaction, detect prompt injection attacks, and validate vision inputs through configurable pre-call and post-call hooks.
The open-source OmniRoute repository (`diegosouzapw/OmniRoute) ships with a production-ready guardrail system designed to secure AI applications without modifying core routing logic. By implementing guardrails in OmniRoute, developers can sanitize sensitive data, block adversarial prompts, and enforce safety policies on vision-enabled models through a unified pipeline architecture.
Understanding the OmniRoute Guardrail Architecture
All guardrails in OmniRoute inherit from BaseGuardrail defined in src/lib/guardrails/base.ts. This abstract class establishes a consistent interface where every guardrail implements preCall (request intercept) and postCall (response intercept) methods.
The guardrail pipeline orchestrates execution through src/lib/guardrails/index.ts. When a request arrives at the API route, the pipeline iterates over registered guardrails from src/lib/guardrails/registry.ts:
- Pre-call phase: Each guardrail's
preCallmethod executes sequentially. If any guardrail returns{ block: true }, the request aborts immediately with an error response. - Provider execution: If all pre-call checks pass, the request proceeds to the underlying LLM provider.
- Post-call phase: After receiving the model response, the pipeline invokes each guardrail's
postCallmethod to sanitize outputs before returning them to the client.
Guardrails are ordered by priority in the registry, allowing high-priority safety checks (like PII masking) to run before lower-priority transformations.
Implementing PII Redaction in OmniRoute
The PII Masker guardrail (src/lib/guardrails/piiMasker.ts) automatically redacts personally identifiable information from both inbound requests and outbound responses.
How PII Redaction Works
The guardrail inspects string fields across the payload—including system, messages, prompt, and input—using the cloneAndMaskRequestPayload function. It delegates actual redaction to processPII from shared/utils/inputSanitizer, controlled by the isRequestPiiMaskingEnabled() feature flag.
On the response side, maskResponsesOutput walks through fields like output_text and output[].content[].text to sanitize any PII that may have leaked from the model.
Enabling PII Protection
Set the environment variable in your .env configuration:
PII_REDACTION_ENABLED=true
When disabled, the guardrail performs a no-op to maintain backward compatibility while remaining in the pipeline.
Usage Example
import { PIIMaskerGuardrail } from '@/lib/guardrails/piiMasker';
const piiGuard = new PIIMaskerGuardrail({ enabled: true });
// Before sending to the model
const preResult = await piiGuard.preCall(requestBody, context);
if (preResult.modifiedPayload) {
requestBody = preResult.modifiedPayload;
}
// After receiving the model response
const postResult = await piiGuard.postCall(modelResponse, context);
if (postResult.modifiedResponse) {
modelResponse = postResult.modifiedResponse;
}
Configuring Prompt Injection Detection
The Prompt Injection Guardrail (src/lib/guardrails/promptInjection.ts) identifies malicious prompt injection attempts using built-in patterns and customizable detection rules.
Detection Logic
The evaluatePromptInjection function orchestrates the validation flow:
- Content extraction:
extractMessageContentsretrieves raw text from the request payload. - Pattern matching:
detectWithPatternsscans the first 16KB of joined message contents against built-in sanitization rules and anycustomPatternsprovided in the configuration. - Severity scoring: Detections are scored using
SHARED_SEVERITY_SCORES. - Action decision:
shouldBlockcompares detection severities against the configuredblockThresholdto determine if the request should be rejected.
Configuration Options
import { PromptInjectionGuardrail } from '@/lib/guardrails/promptInjection';
const injectionGuard = new PromptInjectionGuardrail({
enabled: true,
mode: 'block', // Options: 'warn', 'log', or 'block'
blockThreshold: 'high', // Block only when severity ≥ high
customPatterns: [
{
name: 'dangerous_sql',
pattern: /select\s+.*\s+from\s+/,
severity: 'high'
},
],
});
The guardrail respects the INPUT_SANITIZER_ENABLED feature flag and supports runtime overrides via INJECTION_GUARD_MODE environment variables or database configurations.
Securing Vision Models with Vision Bridge Guardrails
OmniRoute protects vision-enabled endpoints through the Vision Bridge guardrail system, defined in src/lib/guardrails/visionBridge.ts and supporting files.
Safety Validation Layers
The Vision Bridge performs four critical safety checks:
- Image validation: Rejects unsupported formats or oversized blobs before they reach the provider.
- Credential verification: Ensures API keys or OAuth tokens are present and correctly resolved via
resolvePublicCredfromvisionBridgeCredentials.ts. - Rate limiting: Integrates with the global connection-cooldown mechanism to prevent endpoint hammering.
- Output sanitization: Passes vision model responses through the PII masker to prevent data leakage.
Implementation Structure
The Vision Bridge spans multiple specialized files:
| File | Purpose |
|---|---|
visionBridge.ts |
Core guardrail validating image inputs and orchestrating vision model execution |
visionBridgeHelpers.ts |
Utilities for extracting image parts and converting them to data-URIs |
visionBridgeCredentials.ts |
Secure credential handling and secret resolution |
visionBridgeRouter.ts |
Routes vision requests through guardrails and executors |
Integration Example
import { VisionBridgeGuardrail } from '@/lib/guardrails/visionBridge';
const visionGuard = new VisionBridgeGuardrail({
enabled: true,
priority: 15, // Execute after PII masking but before routing
});
// Validate image payload before execution
await visionGuard.preCall(imagePayload, context);
const result = await visionExecutor.execute(imagePayload);
// Sanitize vision model output
await visionGuard.postCall(result, context);
Creating a Custom Guardrail Pipeline
To implement guardrails in OmniRoute for production workloads, assemble the complete pipeline using the guardrail registry pattern:
import { GuardrailContext } from '@/lib/guardrails/base';
import { PIIMaskerGuardrail } from '@/lib/guardrails/piiMasker';
import { PromptInjectionGuardrail } from '@/lib/guardrails/promptInjection';
import { VisionBridgeGuardrail } from '@/lib/guardrails/visionBridge';
// Initialize guardrails in priority order
const guardrails = [
new PIIMaskerGuardrail({ enabled: true }),
new PromptInjectionGuardrail({
mode: 'warn',
blockThreshold: 'medium'
}),
new VisionBridgeGuardrail({ enabled: true }),
];
async function processLlmRequest(payload: unknown) {
const context: GuardrailContext = { log: console };
// Pre-call phase: PII masking and injection detection
for (const guardrail of guardrails) {
const result = await guardrail.preCall(payload, context);
if (result.block) {
throw new Error(result.message ?? 'Blocked by guardrail');
}
if (result.modifiedPayload) {
payload = result.modifiedPayload;
}
}
// Execute against LLM provider
let response = await llmProvider.execute(payload);
// Post-call phase: Sanitize outputs
for (const guardrail of guardrails) {
const result = await guardrail.postCall(response, context);
if (result.modifiedResponse) {
response = result.modifiedResponse;
}
}
return response;
}
Register new guardrails in src/lib/guardrails/registry.ts by extending BaseGuardrail and exporting the class in src/lib/guardrails/index.ts. The registry automatically builds the ordered list based on each guardrail's priority property.
Summary
- Architectural foundation: Guardrails in OmniRoute extend
BaseGuardrailand implementpreCall/postCallmethods orchestrated by the pipeline insrc/lib/guardrails/index.ts. - PII protection: Enable via
PII_REDACTION_ENABLEDto automatically sanitize requests throughcloneAndMaskRequestPayloadand responses throughmaskResponsesOutputinpiiMasker.ts. - Injection defense: Configure
PromptInjectionGuardrailwith custom patterns and severity thresholds; theevaluatePromptInjectionfunction handles detection across the first 16KB of message content. - Vision safety: The Vision Bridge validates images, resolves credentials securely, and enforces rate limits before executing vision models.
- Extensibility: Add custom guardrails by implementing the base interface and registering them in
registry.tswith appropriate priority values.
Frequently Asked Questions
How do I enable PII redaction without blocking legitimate requests?
Set PII_REDACTION_ENABLED=true in your environment variables. The PIIMaskerGuardrail automatically replaces detected PII with redacted tokens while allowing the sanitized request to proceed. The guardrail performs masking rather than blocking, ensuring that legitimate traffic containing accidental PII (like user signatures) is cleaned without service interruption.
Can I use custom regex patterns for prompt injection detection?
Yes. Pass a customPatterns array when instantiating PromptInjectionGuardrail. Each pattern object requires name, pattern (RegExp), and severity properties. The detectWithPatterns function merges these with built-in patterns and scans the first 16KB of request content, allowing you to detect domain-specific injection attempts alongside OmniRoute's default protections.
What happens when a guardrail blocks a request?
When any guardrail's preCall method returns { block: true }, the pipeline immediately aborts and returns an error response to the client without reaching the LLM provider. For the prompt injection guardrail specifically, you can configure the mode parameter as 'warn' (log only), 'log' (structured logging), or 'block' (reject request) to control the behavior when shouldBlock determines the severity meets the threshold.
How does the Vision Bridge handle authentication credentials?
The Vision Bridge uses visionBridgeCredentials.ts to manage provider-specific secrets. It calls resolvePublicCred to safely retrieve API keys or OAuth tokens from environment variables or secure vaults, ensuring credentials are validated before the image payload is forwarded to vision models like Gemini Vision or Claude Vision. This prevents unauthorized access while maintaining clean separation between routing logic and secret management.
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 →