Microsoft Presidio Guardrails
The Presidio guardrail detects and anonymizes sensitive data with Microsoft Presidio, an open-source PII engine you run yourself. AISIX calls your Presidio analyzer for each request or response; detected entities are either blocked or anonymized with an operator you choose, and the traffic continues with the rewritten text.
Compared with the built-in pii guardrail, Presidio adds:
- NER/ML entities a regex cannot express —
PERSON,LOCATION,NRP, and the rest of Presidio's recognizer set. - Anonymize operators: replace with an entity placeholder, mask with asterisks, hash with SHA-256, or redact the span entirely.
- A self-hosted deployment — content is analyzed inside your own network, with no vendor key.
In this guide, you will run Presidio locally, create a Presidio guardrail with per-entity actions, and verify anonymization and blocking.
Prerequisites
Before starting, prepare the following:
- Review Guardrail Behavior for hook points and enforcement modes.
- Docker, to run the Presidio analyzer and anonymizer containers.
- A self-hosted AISIX gateway with the admin and proxy listeners available.
- The admin key from the gateway
config.yaml. - A working model alias and caller API key that can send chat-completions requests.
Run Presidio
Start the two Presidio services:
docker run -d --name presidio-analyzer -p 5002:3000 mcr.microsoft.com/presidio-analyzer:latest
docker run -d --name presidio-anonymizer -p 5001:3000 mcr.microsoft.com/presidio-anonymizer:latest
Both containers must be reachable from the gateway. Confirm the analyzer answers:
curl -sS -X POST "http://127.0.0.1:5002/analyze" \
-H "Content-Type: application/json" \
-d '{ "text": "my email is alice@example.com", "language": "en" }'
The response lists the detected EMAIL_ADDRESS entity with its offsets and score.
Create a Presidio Guardrail
Set the values used by the example requests:
export AISIX_ADMIN_KEY="YOUR_ADMIN_KEY"
export AISIX_API_KEY="YOUR_CALLER_API_KEY"
export AISIX_MODEL="gpt-4o-mini"
Create a guardrail that anonymizes emails and person names but blocks US Social Security Numbers, on both hooks:
curl -sS -X POST "http://127.0.0.1:3001/admin/v1/guardrails" \
-H "Authorization: Bearer ${AISIX_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "presidio-pii-policy",
"enabled": true,
"hook_point": "both",
"fail_open": false,
"kind": "presidio",
"analyzer_url": "http://127.0.0.1:5002",
"anonymizer_url": "http://127.0.0.1:5001",
"entities": [
{ "type": "EMAIL_ADDRESS" },
{ "type": "PERSON" },
{ "type": "US_SSN", "action": "block" }
],
"default_action": "mask",
"operator": "replace",
"language": "en",
"score_threshold": 0.5
}'
❶ Each entry names a Presidio entity. default_action applies to entries without their own action: mask anonymizes and continues, block rejects with 422. An empty entities list analyzes with Presidio's full recognizer set and applies default_action to every hit.
❷ How masked entities are rewritten: replace (default) substitutes <ENTITY_TYPE>, mask overwrites with *, hash substitutes the SHA-256 hex of the value, redact removes the span.
score_threshold drops analyzer results below the given confidence; omit it to accept every result the analyzer returns.
Verify Anonymization
Send a prompt containing an email address:
curl -sSi -X POST "http://127.0.0.1:3000/v1/chat/completions" \
-H "Authorization: Bearer ${AISIX_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "'"${AISIX_MODEL}"'",
"messages": [
{ "role": "user", "content": "email alice@example.com about the order" }
]
}'
The request succeeds. AISIX anonymizes the prompt before calling the upstream model, so the provider receives:
email <EMAIL_ADDRESS> about the order
With hook_point: both, model responses are anonymized the same way before they reach the caller. The original values do not reach the provider, the caller, the gateway log, or the usage record; usage records carry per-entity mask counts (entity names only).
With "operator": "hash", the same prompt reaches the provider with the email replaced by its SHA-256 hex digest — useful when downstream systems need a stable pseudonym instead of a placeholder.
Verify Blocking
A request containing a blocked entity is rejected:
curl -sSi -X POST "http://127.0.0.1:3000/v1/chat/completions" \
-H "Authorization: Bearer ${AISIX_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "'"${AISIX_MODEL}"'",
"messages": [
{ "role": "user", "content": "my ssn is 123-45-6789" }
]
}'
The response starts with HTTP/1.1 422 Unprocessable Entity and the standard content_filter envelope. The matched value is not echoed back.
On endpoints that cannot rewrite request text in place (audio, images, passthrough), a maskable detection blocks instead — AISIX never releases content its policy says should have been anonymized. If the analyzer finds PII but the anonymizer call fails, the failure policy below applies rather than releasing the un-anonymized text.
Failure Policy
| Failure | Bypass reason |
|---|---|
Call timeout (timeout_ms, default 5000, per analyzer/anonymizer call) | presidio_timeout |
| HTTP 429 from Presidio | presidio_throttled |
| HTTP 5xx or connection error | presidio_5xx |
| Other HTTP 4xx (bad URL, language, or entity list) | presidio_config_error |
fail_open: true(default): a failed call lets the request continue un-anonymized and records the bypass reason. For strict PII policies, set it tofalseas in the example above.fail_open: false: a failed call blocks the request.
The output hook has an independent output_fail_open (default false).
Streaming Responses
For output anonymization on streamed responses, AISIX buffers the response, anonymizes it once complete, and then emits the rewritten result — a PII span can cross chunk boundaries. max_buffer_bytes (default 262144) caps the buffer and on_buffer_exceeded (fail_closed default, or fail_open) controls overflow behavior.
Next Steps
If rule-based detection is enough, the in-process pii guardrail avoids running extra services. Start new entity policies in enforcement_mode: monitor and review the hit rate before enforcing — see Guardrail Behavior. To compare all providers, see Choosing a Guardrail Provider.