Skip to main content

Rampart body PII redaction

Three HTTP plugins redact Personally Identifiable Information (PII) directly in the raw body text, on any Otoroshi route (not just LLM routes), using the bundled Rampart model locally (no external call):

  • Rampart request body PII redaction — rewrites the request body before it reaches the backend.
  • Rampart response body PII redaction — rewrites the response body before it returns to the client.
  • Rampart body redaction endpoint — a terminal backend that reads the request body, redacts it, and returns the redacted body directly (no upstream call). Turns a route into a redaction API: POST a body, get the redacted body back.

They share the same configuration and the same detection engine (model + deterministic recognizers + stable placeholders) as the Rampart guardrail.

How it works

  1. The plugin reads the raw body and checks its Content-Type against content_types.
  2. If it matches, the body text is scanned for PII and each value is replaced with a stable placeholder (e.g. [EMAIL_1]).
  3. The rewritten body is forwarded (Transfer-Encoding: chunked).

PII values are replaced in place, so a JSON body stays valid JSON (placeholders live inside the string values).

warning

The body is fully buffered to be rewritten, so these plugins are not suitable for streamed bodies (e.g. SSE LLM streams). For LLM-aware, streaming-friendly redaction with re-inflation, use the Rampart guardrail instead.

On any internal error the plugins fail open (the body is passed through unchanged and the error is logged) so the proxy is never broken by a model glitch.

Plugin references

// request body
"plugin": "cp:otoroshi_plugins.com.cloud.apim.otoroshi.extensions.aigateway.plugins.RampartRequestBodyRedactor"

// response body
"plugin": "cp:otoroshi_plugins.com.cloud.apim.otoroshi.extensions.aigateway.plugins.RampartResponseBodyRedactor"

// redaction endpoint (terminal backend)
"plugin": "cp:otoroshi_plugins.com.cloud.apim.otoroshi.extensions.aigateway.plugins.RampartBodyRedactionBackend"

Configuration

{
"enabled": true,
"plugin": "cp:otoroshi_plugins.com.cloud.apim.otoroshi.extensions.aigateway.plugins.RampartRequestBodyRedactor",
"config": {
"min_score": 0.4,
"entities": ["GIVEN_NAME", "SURNAME", "PHONE", "EMAIL", "SSN", "CREDIT_CARD"],
"content_types": ["application/json", "text/", "application/x-www-form-urlencoded"]
}
}

Parameters

ParameterTypeDefaultDescription
min_scorenumber0.4Confidence floor for the model (lower = more redaction)
entitiesstring[]standard PII setEntity types to redact (see the guardrail for the full list)
content_typesstring[]["application/json", "text/", "application/x-www-form-urlencoded"]Only redact bodies whose Content-Type matches one of these prefixes. Empty list = all content-types.

Example

Request body in:

{ "note": "call Alex Rivera at alex@example.com" }

Request body forwarded to the backend:

{ "note": "call [GIVEN_NAME_1] [SURNAME_1] at [EMAIL_1]" }

The response body plugin works identically on the upstream response before it returns to the client.

Redaction endpoint (terminal backend)

The Rampart body redaction endpoint plugin (RampartBodyRedactionBackend) is a NgBackendCall: instead of forwarding to an upstream, it reads the request body, redacts it, and returns the redacted body as the response, keeping the original Content-Type. This turns any route into a self-contained redaction API — handy for sanitizing payloads before storing or logging them.

It uses the exact same configuration (min_score, entities, content_types) as the request/response plugins above, and the same fail-open behavior.

{
"enabled": true,
"plugin": "cp:otoroshi_plugins.com.cloud.apim.otoroshi.extensions.aigateway.plugins.RampartBodyRedactionBackend",
"config": {
"min_score": 0.4,
"entities": ["GIVEN_NAME", "SURNAME", "PHONE", "EMAIL", "SSN", "CREDIT_CARD"],
"content_types": ["application/json", "text/", "application/x-www-form-urlencoded"]
}
}
curl https://redact.domain.tld/ \
-H "Content-Type: application/json" \
-d '{ "note": "call Alex Rivera at alex@example.com" }'

Response (same content-type, PII replaced in place):

{ "note": "call [GIVEN_NAME_1] [SURNAME_1] at [EMAIL_1]" }

The response carries an X-Rampart-Redaction-Applied: true|false header indicating whether anything was redacted. Bodies whose Content-Type is not in content_types are returned unchanged.