# How to Implement Guardrails in OmniRoute: PII Redaction, Prompt Injection Detection, and Vision Safety

> Learn how to implement robust guardrails in OmniRoute for PII redaction, prompt injection detection, and vision safety. Secure your LLM applications with this modular framework.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-08-22

---

**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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/guardrails/registry.ts):

1. **Pre-call phase**: Each guardrail's `preCall` method executes sequentially. If any guardrail returns `{ block: true }`, the request aborts immediately with an error response.
2. **Provider execution**: If all pre-call checks pass, the request proceeds to the underlying LLM provider.
3. **Post-call phase**: After receiving the model response, the pipeline invokes each guardrail's `postCall` method 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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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:

```bash
PII_REDACTION_ENABLED=true

```

When disabled, the guardrail performs a no-op to maintain backward compatibility while remaining in the pipeline.

### Usage Example

```typescript
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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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:

1. **Content extraction**: `extractMessageContents` retrieves raw text from the request payload.
2. **Pattern matching**: `detectWithPatterns` scans the first 16KB of joined message contents against built-in sanitization rules and any `customPatterns` provided in the configuration.
3. **Severity scoring**: Detections are scored using `SHARED_SEVERITY_SCORES`.
4. **Action decision**: `shouldBlock` compares detection severities against the configured `blockThreshold` to determine if the request should be rejected.

### Configuration Options

```typescript
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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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 `resolvePublicCred` from [`visionBridgeCredentials.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/visionBridgeCredentials.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`](https://github.com/diegosouzapw/OmniRoute/blob/main/visionBridge.ts) | Core guardrail validating image inputs and orchestrating vision model execution |
| [`visionBridgeHelpers.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/visionBridgeHelpers.ts) | Utilities for extracting image parts and converting them to data-URIs |
| [`visionBridgeCredentials.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/visionBridgeCredentials.ts) | Secure credential handling and secret resolution |
| [`visionBridgeRouter.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/visionBridgeRouter.ts) | Routes vision requests through guardrails and executors |

### Integration Example

```typescript
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:

```typescript
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`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/guardrails/registry.ts) by extending `BaseGuardrail` and exporting the class in [`src/lib/guardrails/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/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 `BaseGuardrail` and implement `preCall`/`postCall` methods orchestrated by the pipeline in [`src/lib/guardrails/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/guardrails/index.ts).
- **PII protection**: Enable via `PII_REDACTION_ENABLED` to automatically sanitize requests through `cloneAndMaskRequestPayload` and responses through `maskResponsesOutput` in [`piiMasker.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/piiMasker.ts).
- **Injection defense**: Configure `PromptInjectionGuardrail` with custom patterns and severity thresholds; the `evaluatePromptInjection` function 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.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/registry.ts) with 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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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.