feat(pii): restore request-scoped pseudonyms (#11272)

* feat(pii): restore request-scoped pseudonyms

Replace masked request values with unique per-request tokens when response restoration is enabled, then restore them across JSON and SSE write boundaries. Document the opt-in model setting and expose it in config metadata.\n\nAssisted-by: Codex:gpt-5

* fix(pii): wrap reversible redaction tokens

Use configurable token delimiters to avoid restoring ordinary model text that happens to match an internal identifier. Rename the option and document the confidentiality tradeoff.

Assisted-by: Codex:gpt-5

---------

Co-authored-by: localai-org-maint-bot <306269227+localai-org-maint-bot@users.noreply.github.com>
This commit is contained in:
localai-org-maint-botandlocalai-org-maint-bot authored and GitHub committed 2026-08-09 22:37:13 +02:00
1 parent a0f50b2af2
commit 06ff56e674
6 files changed
+276 -6

No files matched your search

+20 -2
View File
@@ -165,15 +165,33 @@ pii:
enabled: true # default-on for cloud-proxy; explicit for audit
detectors:
- privacy-filter-multilingual
reversible_redactions: true # restore request PII if the model echoes its wrapped token
reversible_token_prefix: "[REDACTED:" # optional; this is the default
reversible_token_suffix: "]" # optional; this is the default
```
`reversible_redactions` enables bijective, request-scoped replacement. Each
masked value is sent to the backend as a stable wrapped token such as
`[REDACTED:EMAIL_001]` instead of a generic redaction marker. If the model includes that token in
its response, LocalAI restores the original value before returning JSON or SSE
to the caller. The substitution map exists only for that request and is never
logged or persisted. Leave the option unset (the default) for irreversible
`[REDACTED:...]` masking.
The prefix and suffix reduce collisions with ordinary model output and can be
customized with `reversible_token_prefix` and `reversible_token_suffix`.
Reversible redactions provide less confidentiality than irreversible masking:
any third party that can observe both the redacted request and restored response
may be able to infer the original values.
Multiple detectors **union** their detections; overlapping spans resolve to
the strongest action (`block` > `mask` > `allow`). A configured detector
that can't be loaded **fails the request closed** (HTTP 503,
`error.type=pii_ner_unavailable`) rather than silently skipping the check.
The same NER path runs on the [MITM proxy]({{< relref "mitm-proxy.md" >}})
request body for intercepted hosts. Response/output redaction is out of
scope for now.
request body for intercepted hosts. Reversible response restoration currently
applies to LocalAI API routes; the MITM proxy keeps its own output-redaction
policy.
### Instance-wide default detector