# How the promptInjectionGuard in OmniRoute Protects Chat Completions from Injection Attacks

> Discover how OmniRoute's promptInjectionGuard safeguards chat completions from injection attacks by detecting and blocking malicious payloads before they reach LLM providers.

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

---

**The promptInjectionGuard in OmniRoute intercepts malicious payloads before they reach LLM providers by evaluating request content against configurable regex patterns, aggregating severity scores, and either blocking the request with a 400 error or logging it based on the active guard mode.**

OmniRoute is an open-source AI gateway that secures chat completion endpoints through a multi-layer defense system. The **promptInjectionGuard** serves as the primary barrier against adversarial prompt manipulation, processing every request through a sanitization pipeline before forwarding to upstream providers. This guardrail ensures that system-override directives and malformed injection patterns never compromise model behavior.

## Middleware Entry Point and Request Wrapping

Every chat completion request first passes through the `withInjectionGuard` middleware defined in [`src/middleware/promptInjectionGuard.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/middleware/promptInjectionGuard.ts). This wrapper intercepts POST, PUT, and PATCH requests before they reach route handlers.

The middleware clones the incoming `Request` object, parses the JSON payload, and passes the parsed body to the guardrail evaluation function:

```typescript
// src/middleware/promptInjectionGuard.ts
export const withInjectionGuard = (
  handler: RequestHandler,
  options?: GuardOptions
): RequestHandler => {
  return async (req, res) => {
    const body = await req.clone().json();
    const result = await guard(body, options);
    
    if (result.blocked) {
      return res.status(400).json({
        error: "Request blocked: potential prompt injection detected"
      });
    }
    return handler(req, res);
  };
};

```

When the guard returns `{ blocked: true }`, the middleware immediately terminates the request with a 400 status code, preventing any downstream provider contact.

## The Core Detection Pipeline

The actual detection logic resides in [`src/lib/guardrails/promptInjection.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/guardrails/promptInjection.ts). The `evaluatePromptInjection` function orchestrates a multi-stage analysis pipeline:

1. **Initial Sanitization**: The `sanitizeRequest` utility from [`src/shared/utils/inputSanitizer.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/shared/utils/inputSanitizer.ts) performs first-pass regex checks against the payload, producing an initial set of detections.

2. **Pattern Scanning**: The system normalizes default patterns (`DEFAULT_GUARD_PATTERNS`) and any user-supplied `customPatterns` using `normalizePatternEntry`, then scans the first 16 KB of joined message contents (bounded by `MAX_INJECTION_SCAN_BYTES`).

3. **Severity Aggregation**: Detections are merged and flagged, with the overall severity compared against the configured block threshold via `resolveBlockThreshold`.

High-severity matches—such as `system: override` directives or malformed system blocks (```` ```system````)—trigger immediate escalation.

## Configuration Modes and Feature Flags

The guard supports three operational modes determined by a hierarchical resolution chain:

- **Database feature flag**: `INJECTION_GUARD_MODE` (defined in `src/shared/constants/featureFlagDefinitions.ts`)
- **Environment variable**: `INJECTION_GUARD_MODE` or `INPUT_SANITIZER_MODE`
- **Default**: `"warn"` mode

The resolution logic in `src/lib/guardrails/promptInjection.ts` reads:

```typescript
const mode = (await getFeatureFlag('INJECTION_GUARD_MODE')) 
  ?? process.env.INJECTION_GUARD_MODE 
  ?? process.env.INPUT_SANITIZER_MODE 
  ?? 'warn';

```

The guard is enabled by default via the `INPUT_SANITIZER_ENABLED` environment variable (defaulting to `true` if absent). The three modes determine the enforcement level:

- **`block`**: Rejects requests exceeding the severity threshold
- **`warn`**: Allows the request but logs warnings
- **`log`**: Allows the request with informational logging only

## Blocking Behavior and Response Handling

When operating in `block` mode with a severity level above the configured threshold, the guard returns a blocking decision that propagates through the middleware stack. The chat completion route in `src/app/api/v1/chat/completions/route.ts` implements the same error path, ensuring consistent rejection behavior across endpoints.

The standard error response includes:

```json
{
  "error": "Request blocked: potential prompt injection detected"
}

```

This response is generated both by the middleware wrapper and directly within route handlers that manually invoke the guard evaluation.

## Practical Implementation Examples

### Wrapping a Custom API Route

Apply the guard to specific endpoints with custom thresholds and patterns:

```typescript
import { withInjectionGuard } from "@/middleware/promptInjectionGuard";
import { handler as chatHandler } from "./chatCore";

export default withInjectionGuard(chatHandler, {
  blockThreshold: "high",
  customPatterns: [/my_secret_keyword/i],
});

```

### Configuring Tenant-Specific Mode via Database

Override the guard behavior for specific tenants using the feature flag system:

```sql
INSERT INTO feature_flags (name, value) 
VALUES ('INJECTION_GUARD_MODE', 'block');

```

This forces **block** mode for all requests belonging to that tenant, superseding environment variable configurations.

### Manual Guard Evaluation

Access the guard's decision logic directly within business logic:

```typescript
import { evaluatePromptInjection } from "@/lib/guardrails/promptInjection";

async function myEndpoint(req: Request) {
  const body = await req.json();
  const decision = evaluatePromptInjection(body, {}, { log: console });

  if (decision.blocked) {
    return new Response(
      JSON.stringify({ error: "Injection detected" }), 
      { status: 400 }
    );
  }
  
  // Proceed with normal processing
}

```

## Summary

- **Pre-provider interception**: The `withInjectionGuard` middleware in `src/middleware/promptInjectionGuard.ts` processes requests before they reach upstream LLM providers.
- **Multi-layer detection**: The pipeline combines `sanitizeRequest` regex checks with normalized pattern scanning against the first 16 KB of message content.
- **Configurable enforcement**: Modes (`block`, `warn`, `log`) are resolved via database feature flags `INJECTION_GUARD_MODE`, environment variables, or sensible defaults.
- **Immediate termination**: Blocked requests receive a 400 status code with the message "Request blocked: potential prompt injection detected", preventing any provider forwarding.
- **Extensible patterns**: Developers can supply `customPatterns` and adjust `blockThreshold` per endpoint or tenant.

## Frequently Asked Questions

### What types of prompt injection attacks does the guard detect?

The guard identifies system-override directives (e.g., `system: override`), malformed delimiter blocks (```` ```system````), and user-defined patterns. It scans the joined message contents using regex patterns from `DEFAULT_GUARD_PATTERNS` combined with any `customPatterns` provided during middleware initialization, evaluating against severity thresholds to distinguish between suspicious and benign inputs.

### How do I configure the guard to block requests for one tenant while warning for others?

Set the `INJECTION_GUARD_MODE` feature flag in your database to `'block'` for the specific tenant ID. The resolution logic in [`src/lib/guardrails/promptInjection.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/guardrails/promptInjection.ts) checks database flags before environment variables, allowing per-tenant overrides. For other tenants, omit the flag or set it to `'warn'` to allow requests with logging.

### What happens if the detection service fails or times out?

The guard defaults to enabled status (`INPUT_SANITIZER_ENABLED` defaults to true) and evaluates entirely within the request lifecycle without external service dependencies. If pattern matching or JSON parsing fails, the error propagates as a standard 400 or 500 response rather than silently allowing potentially malicious requests to pass through.

### Can I use the promptInjectionGuard outside of chat completion routes?

Yes. The `withInjectionGuard` middleware and `evaluatePromptInjection` function are provider-agnostic. You can wrap any POST/PUT/PATCH handler or call the evaluation logic directly in custom endpoints, supplying options like `customPatterns` and `blockThreshold` to tailor detection for specific use cases beyond standard chat completions.