PII Detection & Redaction
AxonFlow provides built-in detection and redaction of Personally Identifiable Information (PII) in LLM interactions. The system uses a hybrid approach combining fast regex-based pattern matching with intelligent validation to minimize false positives while maintaining sub-millisecond latency.
AxonFlow performs PII detection and redaction server-side; your integration calls AxonFlow's endpoints and forwards what they return. Your gateway, proxy, plugin, or SDK must not carry its own PII patterns or redaction logic — a hand-rolled client-side redactor is a different, unverified path and a governance gap, not a shortcut. In Decision Mode, POST /api/v1/decide returns a verdict plus self-describing obligations: a redact_pii obligation names the engine endpoint to call to discharge it. Redaction is a symmetric pair — POST /api/v1/mcp/check-input redacts a request, POST /api/v1/mcp/check-output redacts a response — so a governed exchange is a two-touch flow (decide → fulfill via the named endpoint → forward). See Decision Mode: two-touch redaction below.
Detection vs Policy
Detection identifies what happened. Policies determine what action to take.
For example, PII detection can be enabled while policies are configured to log-only during development, and later switched to block or require_approval in production — without changing application code.
This separation allows AxonFlow to support experimentation, audits, and enforcement within the same architecture.
Supported PII Types
Global PII Types
| Type | Severity | Example | Validation |
|---|---|---|---|
| Credit Card | Critical | 4532-0151-1283-0366 | Luhn algorithm |
| Medium | [email protected] | RFC 5322 format | |
| Phone | Medium | (555) 123-4567 | Format + context |
| IP Address | Medium | 192.168.1.100 | IPv4 validation |
| Passport | High | AB1234567 | Format + context |
| Date of Birth | High | 01/15/1990 | Context-dependent |
| Booking Reference | Low | ABC123 | 6-char alphanumeric |
United States PII Types
| Type | Severity | Example | Validation |
|---|---|---|---|
| SSN | Critical | 123-45-6789 | Area/group/serial rules |
| Bank Account | Critical | 021000021-123456789 | ABA routing checksum |
European Union PII Types
| Type | Severity | Example | Validation |
|---|---|---|---|
| IBAN | Critical | DE89370400440532013000 | MOD 97 checksum |
India PII Types
| Type | Severity | Example | Validation |
|---|---|---|---|
| India PAN | Critical | ABCDE1234F | 10-char format with entity type |
| India Aadhaar | Critical | 2345 6789 0123 | 12-digit with Verhoeff checksum |
Singapore PII Types (MAS FEAT)
Singapore PII detection is now available in AxonFlow Community Edition. See MAS FEAT Compliance.
| Type | Severity | Example | Validation |
|---|---|---|---|
| NRIC | Critical | S1234567D | 9-char with prefix S/T/M |
| FIN | Critical | F1234567N | 9-char with prefix F/G |
| UEN | High | 200312345A | 8-10 digit business registration |
| SG Phone | Medium | +65 9123 4567 | +65 format, 8-digit |
| SG Postal | Low | 238877 | 6-digit Singapore postal |
NRIC Prefixes:
S- Citizen born before 2000T- Citizen born 2000+M- Foreigner from 2022+F- Foreigner before 2000G- Foreigner 2000-2021
How It Works
Two-Layer Detection
- Agent Layer (Static Engine): Fast regex-based detection (<1ms) that flags potential PII for downstream processing
- Orchestrator Layer (Enhanced Detector): Deep validation with Luhn, MOD 97, and context-aware confidence scoring
False Positive Prevention
The enhanced detector uses context analysis to reduce false positives:
Input: "Order number: 123-45-6789"
→ Context contains "order" → Low confidence (not flagged as SSN)
Input: "Customer SSN: 123-45-6789"
→ Context contains "SSN" → High confidence (flagged as SSN)
Context-gated detectors (label required)
Several PII types share a shape with ordinary business data — a 12‑digit number, a
letter+7digits+letter id, a 4‑part dotted version, a 10‑digit reference. To avoid
masking benign values (order ids, barcodes, asset tags, build numbers, tracking ids),
these detectors require a label or indicator adjacent to the value before they fire.
A bare, unlabelled value of the same shape is not governed.
| Detector | Governed when… | Not governed (benign) |
|---|---|---|
| Aadhaar (bare 12‑digit) | an aadhaar / UID label is adjacent (aadhaar 2345 6789 0123) | barcode 234567890123 |
| Singapore NRIC / FIN | an NRIC / FIN / identity‑card label is adjacent | asset tag S1234567Z |
| Singapore UEN / Postal | a UEN / Singapore / postal code label is adjacent | order 12345678X, route 408600 |
| Passport / Date of Birth | a passport / birth‑date label is adjacent | order X1234567, invoice 03/04/2025 |
| IP Address | not preceded by a version label | {"ver":"10.20.30.40"}, build 1.2.3.4 |
| Indonesian phone | a real mobile (≥7 digits after 8X) | short id 6281234509 |
The gate is deliberately conservative: an unlabelled value that merely looks like one of these types is left untouched rather than masked. Detectors backed by a checksum (credit card / Luhn, IBAN / MOD‑97, Aadhaar / Verhoeff, NIK / province+date) validate the value itself and do not depend on a label.
Configuration
Environment Variable Configuration
Configure PII detection behavior using environment variables:
| Variable | Values | Default | Description |
|---|---|---|---|
PII_ACTION | block, warn, redact, log | warn (v6.2.0+) | Action when PII is detected |
AXONFLOW_PROFILE | dev, default, strict, compliance | default (v7.0.0+) | Bundles per-category actions. See Governance Profiles. |
Actions:
block- Reject request with HTTP 403warn- Log warning, allow request through unchanged (v6.2.0+ default)redact- Mask detected PII with category-tagged placeholders (e.g.,[REDACTED:ssn]), allow requestlog- Log for audit only, allow unmodified
redact or blockwarn and log detect for audit but never modify the content. Checksum-validated
national IDs (Indonesian NIK / NPWP) are masked only under PII_ACTION=redact, and
hard‑denied under PII_ACTION=block. If you need these values masked in responses, set
redact (or block) — warn/log will record the detection but pass the value through
unchanged.
# v6.2.0+ default: PII is flagged in audit but the request flows through
docker compose up -d
# Restore the v6.1.0 behavior — PII masked with [REDACTED:*]
PII_ACTION=redact docker compose up -d
# Block requests containing PII (recommended for production)
PII_ACTION=block docker compose up -d
# Or use the strict profile which sets PII, SQLi, and sensitive data to block
AXONFLOW_PROFILE=strict docker compose up -d
PII detection now defaults to warn (flag but do not mutate the data). The previous default was redact. Silent redaction was breaking debugging flows — see Governance Profiles for the full rationale and the new profile matrix.
Gateway Mode
PII detection is automatically applied during the gateway pre-check flow:
# Pre-check detects PII in prompts
curl -X POST https://api.example.com/api/policy/pre-check \
-H "Content-Type: application/json" \
-d '{
"user_token": "user-123",
"client_id": "community",
"query": "Customer SSN: 123-45-6789",
"context": {}
}'
Response includes policy and redaction context:
{
"approved": true,
"requires_redaction": true,
"policies": ["sys_pii_ssn"],
"context_id": "ctx_abc123"
}
SDK Usage
See complete working examples in the AxonFlow examples repository.
Python
from axonflow import AxonFlow
async with AxonFlow(
endpoint="http://localhost:8080",
client_id="your-client-id",
client_secret="your-secret",
) as client:
result = await client.get_policy_approved_context(
user_token="user-123",
query="Process refund for SSN 123-45-6789",
)
if not result.approved:
print(f"Blocked: {result.block_reason}")
elif result.policies:
print(f"Policies triggered: {result.policies}")
TypeScript
import { AxonFlow } from '@axonflow/sdk';
const axonflow = new AxonFlow({
endpoint: 'http://localhost:8080',
clientId: 'your-client-id',
clientSecret: 'your-secret',
});
const result = await axonflow.getPolicyApprovedContext({
userToken: 'user-123',
query: 'Process refund for SSN 123-45-6789',
});
if (!result.approved) {
console.log(`Blocked: ${result.blockReason}`);
}
Go
import "github.com/getaxonflow/axonflow-sdk-go/v8"
client := axonflow.NewClient(axonflow.AxonFlowConfig{
Endpoint: "http://localhost:8080",
})
result, err := client.GetPolicyApprovedContext(
"user-123",
"Process refund for SSN 123-45-6789",
nil, nil,
)
if !result.Approved {
log.Printf("Blocked: %s", result.BlockReason)
}
Java
import com.getaxonflow.sdk.AxonFlow;
import com.getaxonflow.sdk.AxonFlowConfig;
import com.getaxonflow.sdk.types.*;
AxonFlow client = AxonFlow.create(AxonFlowConfig.builder()
.endpoint("http://localhost:8080")
.build());
PolicyApprovalResult result = client.getPolicyApprovedContext(
PolicyApprovalRequest.builder()
.query("Process refund for SSN 123-45-6789")
.userToken("user-123")
.build()
);
if (!result.isApproved()) {
System.out.println("Blocked: " + result.getBlockReason());
}
Redaction Behavior
When PII is detected, the exact behavior depends on your configured action:
| Action | Runtime behavior | Typical use |
|---|---|---|
redact | Request continues with detected values masked or removed | Default for production systems that need continuity |
block | Request is rejected during pre-check or request processing | Strict regulated workflows |
warn | Request continues and detection is recorded | Rollout and tuning |
log | Request continues and detection is written to audit | Observation and evidence collection |
If you need different behavior by execution path, use the mode-specific overrides:
PII_ACTIONfor the shared defaultMCP_PII_ACTIONfor connector/MCP trafficGATEWAY_PII_ACTIONfor gateway-mode requests
Decision Mode: two-touch redaction
In Decision Mode, your infrastructure gateway asks AxonFlow for a verdict and enforces it — AxonFlow is never on the traffic path. AxonFlow does all the PII work; your gateway calls AxonFlow's endpoints and forwards what they return. The blessed path is decide → fulfill the obligation via the named endpoint → forward.
Touch 1 — decision. The gateway calls POST /api/v1/decide. This is a decision-only endpoint: it returns a verdict (allow / deny / needs_approval), reasons, a correlation id, and obligations — and it never mutates content (no redacted payload is returned, and /decide does not see the response). When a policy requires redaction, the decision carries a self-describing obligation whose fulfillment block names the engine endpoint to call:
{
"verdict": "allow",
"obligations": [
{ "type": "redact_pii", "detail": "...",
"fulfillment": { "endpoint": "/api/v1/mcp/check-input", "method": "POST",
"phase": "request", "content_types": ["text/plain"] } }
],
"decision_id": "dec_abc123"
}
A redact_pii obligation is an instruction to call the engine — not something your gateway fulfills with its own code.
Touch 2 — fulfillment. The gateway sends the content to the endpoint the obligation names and forwards the engine-redacted result. Request and response redaction are a symmetric pair:
POST /api/v1/mcp/check-inputreturns an engine-redacted request (redacted_statement).POST /api/v1/mcp/check-outputreturns an engine-redacted response (redacted_datafor rows,redacted_messagefor a string).
The fail-closed signal — redaction_evaluated. On the check-input (request) leg, the allow response carries a boolean redaction_evaluated. It is the difference between "the detector ran and found nothing" and "the detector never ran" — and a PEP must treat those two cases differently:
check-input field | Meaning for the PEP |
|---|---|
redaction_evaluated: true | The redactor ran. Read redacted / redacted_statement and forward the engine-masked statement. |
redaction_evaluated: false (or absent) | The redactor did not run (no detection config enabled). redacted: false here would be indistinguishable from "looked, found nothing," so the PEP MUST fail closed — do not forward the statement as if it were clean. |
There is no redaction_evaluated field on check-output: /decide is pre-call and only emits request-phase obligations, so the response leg is driven by the PEP's own check-output call and fails closed on any unsuccessful engine round-trip (non-2xx, allowed: false, timeout, or an unexpected redacted_data shape). For the full set of rules see Building a Policy Enforcement Point.
Client → Gateway ──(1) POST /api/v1/decide ─────────────────→ AxonFlow → allow + obligation (names endpoint)
Gateway → Backend (forward request) → raw response
Gateway ──(2) POST <obligation endpoint> (content) ─────────→ AxonFlow → engine-redacted content
Gateway → Client (forward redacted content)
The reference PEP client (platform/shared/pep) carries no PII patterns — its only redaction path is that engine round-trip, and it fails closed if an obligation can't be discharged through the engine. The redaction contract is content-type-aware: an obligation advertises the content_types the engine can handle, and a request for an unsupported content type is rejected (415) rather than forwarded ungoverned (today text/plain is wired; media routes to AxonFlow's media-governance subsystem). Coverage is policy-derived — the PII categories your active policies enable — and gateway detection is connector-agnostic: AxonFlow governs whatever content you submit, with no "enabled connector" prerequisite.
POST /api/v1/decidenever returns content. UnderPII_ACTION=block, request-phase PII is denied rather than redacted. Redacted content always comes back from the engine'scheck-input/check-outputendpoints, never from client-side code.
Performance
| Operation | Latency | Notes |
|---|---|---|
| Single type detection | ~1μs | Type-specific check |
| Full detection (no PII) | ~17μs | All patterns |
| Full detection (with PII) | ~25μs | With validation |
| Long text (10KB) | ~1.4ms | Comprehensive scan |
Compliance
AxonFlow's PII detection helps with compliance requirements:
| Regulation | Supported PII Types |
|---|---|
| PCI-DSS | Credit card numbers, bank accounts |
| HIPAA | SSN, DOB |
| GDPR | Email, phone, IP address |
| CCPA | SSN, email, phone |
Best Practices
- Enable validation for financial data (credit cards, bank accounts)
- Use context to reduce false positives
- Tune actions by environment so staging can warn while production blocks or redacts
- Log PII detection events for audit trails
- Test with realistic data to tune confidence thresholds
See Also
- Media Governance -- PII detection is also applied to text extracted from images via OCR as part of the media governance pipeline
- Security Best Practices
- Policy Configuration
- Gateway Mode
Operational Readiness Checklist
Before relying on this page in a production rollout, pair it with the core operations docs:
- Deployment Mode Matrix for self-hosted, Evaluation, Enterprise, SaaS, and In-VPC fit
- Failure Modes And Recovery for degraded-provider, connector, approval, and runtime behavior
- Capacity Planning for sizing and growth signals
- Community vs Evaluation vs Enterprise for limits, support surfaces, and upgrade triggers
