Content Guard
The Content Guard middleware detects and processes sensitive or restricted content in requests and responses. It allows you to:
- Block specific content (such as personally identifiable information or disallowed phrases) in either requests or responses, preventing it from reaching any upstream service or being returned to the client.
- Mask sensitive content in both requests and responses, preserving confidentiality and ensuring compliance.
For the AI Gateway, the Content Guard middleware empowers enterprises to responsibly deploy LLMs by ensuring that sensitive or non-compliant content never reaches AI models—or end users. Whether protecting customer privacy, enforcing corporate policy, or complying with regulations like HIPAA and GDPR, Content Guard adds a critical safety net for all AI-driven interactions.
Key Features and Benefits
- Prevent data leakage by blocking PII or sensitive information in inputs and outputs
- Mask content instead of blocking, maintaining UX while enforcing policies
- Use custom detection rules for internal codes or region-specific regulations
- Track violations and compliance metrics through integrated observability
Requirements
-
AI Gateway must be enabled:
helm upgrade traefik -n traefik --wait \
--reuse-values \
--set hub.experimental.aigateway=true \
traefik/traefik -
An external content detection engine is required. Currently, we support presidio as the content detection engine.
-
Configure the detection engine endpoint in the middleware definition.
How It Works
When the Content Guard middleware intercepts an HTTP request or response:
-
Identify Relevant JSON Fields: You specify which parts of the JSON body to analyze for sensitive data. For example, you might target user messages in a request or AI-generated text in a response.
-
Analyze Detected Text: The external engine (Presidio) checks whether the targeted text contains any specified “entities” (e.g.,
PERSON
,EMAIL_ADDRESS
,LOCATION
). For a complete list of supported entities, see Presidio Supported Entities -
Block or Mask
- Block: If you mark a rule to “block” and the engine finds a match, the middleware returns a 403 Forbidden, stopping the request or response.
- Mask: If instead you specify a “mask,” the matched portions are replaced with a chosen character pattern (for example, using * or #), optionally revealing a few characters from the beginning or end.
-
Custom Entities: In addition to built-in Presidio entities, you can define your own entity patterns. This can be helpful for organization-specific data formats like employee IDs or internal codes. For more details, please see the Custom Entities section.
Configuration Example
Below is an example demonstrating how to block certain content in requests and mask it in responses:
- Middleware
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
namespace: traefik
name: content-guard
spec:
plugin:
content-guard:
engine:
presidio:
host: http://presidio
language: en
request:
rules:
- jsonPaths:
- ".messages[].content"
block: true
entities:
- PERSON
- LOCATION
response:
rules:
- jsonPaths:
- ".choices[].message.content"
mask:
char: "*"
unmaskFromLeft: 2
unmaskFromRight: 2
entities:
- PERSON
- LOCATION
Configuation Options
Key | Description | Required | Default |
---|---|---|---|
engine.presidio.host | The base URL of your Presidio analyzer instance. | yes | |
engine.presidio.language | Language code used by Presidio for detection (e.g., en ). | yes | |
engine.presidio.entities | Optional list of entity types to detect (e.g. PHONE_NUMBER , EMAIL_ADDRESS ). If not set, Presidio uses all known entity types. | no | |
request.rules | An array of rule objects for incoming traffic. Each rule can specify jsonPaths , block , mask , and a list of entities . | no | |
request.rules[].jsonPaths | A list of gojq-style JSON paths to scan in the request (e.g., ".messages[].content" ). | yes | |
request.rules[].block | If true , any match triggers 403 Forbidden for the request. | no | false |
request.rules[].mask | Defines how matched text is masked if block is false . This object can contain char , unmaskFromLeft , unmaskFromRight . | no | |
request.rules[].mask.char | Character used to replace matched text. | yes (if using mask) | * |
request.rules[].mask.unmaskFromLeft | Number of characters to leave unmasked at the start of a match. | no | 0 |
request.rules[].mask.unmaskFromRight | Number of characters to leave unmasked at the end of a match. | no | 0 |
request.rules[].entities | List of entities to look for. If omitted, Presidio attempts to detect all known entities. For a complete list of supported entities, see Presidio Supported Entities | no | |
response.rules | An array of rule objects for outgoing traffic. Each rule can also specify jsonPaths , block , mask , entities . | no | |
response.rules[].jsonPaths | A list of JSON paths to scan in the response body. | yes | |
response.rules[].block | If true , any match triggers 403 Forbidden for the response. | no | false |
response.rules[].mask | Defines how matched text is masked if block is false . Can contain char , unmaskFromLeft , unmaskFromRight . | no | |
response.rules[].mask.char | Character used to replace matched text. | yes (if using mask) | * |
response.rules[].mask.unmaskFromLeft | Number of characters to leave unmasked at the start of a match. | no | 0 |
response.rules[].mask.unmaskFromRight | Number of characters to leave unmasked at the end of a match. | no | 0 |
response.rules[].entities | List of entities to detect. If omitted, Presidio attempts to detect all known entities. For a complete list of supported entities, see Presidio Supported Entities | no |
Custom Entities
You can define additional entities for Presidio to detect (such as specialized IDs or formats). These are typically added in Presidio’s configuration itself, or via its “custom analyzer” endpoints. Once added, you can reference them in the entities array like built-in types. For more details, please see the Presidio Custom Analyzer documentation.
Request vs. Response Rules
- Request Rules: Often used to block disallowed content before it ever arrives at the AI. For example, if a request includes personal information in .messages[].content, you can instantly return a 403 Forbidden.
- Response Rules: If your AI might return sensitive data (like phone numbers or addresses), you can mask that content before sending the response to the user. In unusual cases, you can also block the entire response.