# How OmniRoute's Guardrail System Prevents Prompt Injection and Credential Leakage

> Discover how OmniRoute's guardrail system prevents prompt injection and credential leakage. Learn how its hot-reloadable registry with pre/postCall hooks secures your LLM communications.

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

---

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

1. **Sanitization**: The payload runs through `sanitizeRequest` for baseline injection detection
2. **Pattern scanning**: The first 16KB of concatenated message contents (`MAX_INJECTION_SCAN_BYTES`) is scanned against custom patterns
3. **Result merging**: New detections merge with the sanitizer's findings
4. **Decision**: If mode is `"block"` and accumulated severity exceeds `blockThreshold`, 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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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 `modifiedPayload` with 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`](https://github.com/diegosouzapw/OmniRoute/blob/main/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:

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

```bash

# 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`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/guardrails/base.ts) | Abstract base class defining the guardrail interface |
| [`src/lib/guardrails/registry.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/guardrails/registry.ts) | Orchestrates guardrail execution order and hook invocation |
| [`src/lib/guardrails/promptInjection.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/guardrails/promptInjection.ts) | Prompt injection detection (lines 49-85, 92-120, 162-184, 210-227, 248-267) |
| [`src/lib/guardrails/credentialMasker.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/guardrails/credentialMasker.ts) | API key and secret token redaction |
| [`src/lib/guardrails/piiMasker.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/guardrails/piiMasker.ts) | Personal data identification and removal |
| [`docs/security/GUARDRAILS.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/docs/security/GUARDRAILS.md) | Architecture and configuration documentation |

---

## Summary

- **Hot-reloadable registry** ([`src/lib/guardrails/registry.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/guardrails/registry.ts)) chains guardrails with `preCall` and `postCall` hooks
- **Fail-open design** logs errors but continues processing unless explicit block returned
- **Prompt injection guardrail** uses `DEFAULT_GUARD_PATTERNS`, severity scoring, and configurable `blockThreshold` with `INJECTION_GUARD_MODE` control
- **Credential masker** redacts secrets via `CREDENTIAL_REDACTION_ENABLED` before provider handoff
- **Per-request overrides** supported via `x-omniroute-disabled-guardrails` header
- **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.