Privacy Filter Nigeria: A context-aware domain adapter for Nigerian identity systems
OpenRay.ai
PROJECT 02 / EKŌ

Every AI prompt is a potential data breach.

A support agent pastes a customer ticket into ChatGPT to summarize it. An internal copilot threads KYC or compliance notes through a third-party model. Once that text lands in a provider's logs, the only honest answer to “where is it now?” is “we don't know.”

Ekō is an open-source security proxy that sits between your applications and AI providers. It catches credentials, PII, and regulated identifiers in every prompt, then either redacts the values or replaces them with reversible session tokens — with first-class detection for African banking, fintech, and health workflows.

EKŌ PROXY
GO / DOCKER / 24+ PATTERNS
SECURITY INFRASTRUCTURE / 2026

What happens to a real prompt

A single support-ticket sentence exercises both layers of Ekō at once. The deterministic pattern engine catches structured identifiers — BVN, phone numbers, account numbers — while the optional SLM sidecar handles the entities a regex layer cannot reach reliably: person names, addresses, and context-dependent spans.

Input text

“Amina Yusuf can be reached at +234 802 111 3344. Her BVN is 22334455667 and she lives at No. 30 Ikeja Road, Lagos. Amina Obi is the head of IT and in charge of database administration”

Original
JSON
{
  "original_prompt": "Amina Yusuf can be reached
    at +234 802 111 3344. Her BVN is 22334455667
    and she lives at No. 30 Ikeja Road, Lagos.
    Amina Obi is the head of IT and in charge
    of database administration"
}
After Ekō
JSON
{
  "sanitized_prompt": "Xxxxx Xxxxc can be reached
    at +234 000 000 0001. Her BVN is 00000000001
    and she lives at Xx. 02 Xxxxx Xxxx, Xxxxx.
    Xxxxx Xxa is the head of IT and in charge
    of database administration"
}

The phone number and BVN are caught by the deterministic pattern layer — the kind of value a generic DLP often passes through unchanged because an 11-digit number is, to a generic detector, just an 11-digit number.

The two names (Amina Yusuf and Amina Obi) and the address are caught by the optional SLM sidecar. The model treats the two Aminas as distinct entities rather than collapsing them into a single token — which is what you want when the same prompt references two different people.

What is not redacted matters as much as what is. The clause “head of IT and in charge of database administration” survives untouched. The downstream model still gets a coherent ticket it can summarize or route; the regulated identifiers and the human identities are gone before they ever reach a provider's logs.

The output also shows the system honestly. Yusuf → Xxxxc and Obi → Xa are real span-boundary artifacts of the current SLM. We preserve format and length rather than collapse everything to [REDACTED] because most downstream consumers — summarizers, classifiers, human reviewers — work better when the shape of the original is intact. The trade-off is occasional one-character span drift, which is what a recall-oriented model looks like in production.

Why the standard answers don't cover this

Banks and fintechs are shipping customer-facing AI and wiring employees into internal models for document review and code generation. Every prompt is a potential leak vector, and the existing controls do not close the gap.

Private hosting ≠ sanitization

Azure OpenAI and AWS Bedrock keep the network private, but they will faithfully forward a BVN, a JWT, or a customer's address to the model exactly as written.

Manual review doesn't scale

Per-prompt human review collapses the moment AI features see real traffic. The volume that makes AI useful is the same volume that makes review impossible.

Training doesn't survive deadlines

Security training sets the intent, but a tired engineer pasting a stack trace at 6pm is operating on muscle memory, not policy. Behavioural controls fail under load.

Homemade regex catches the easy 60%

A weekend script will find credit cards and email addresses, then silently miss the half-formatted account numbers, regional ID schemes, and names that actually matter.

Two ways to deploy

Drop-in OpenAI Proxy

Point your OpenAI SDK at Ekō instead of api.openai.com. Chat completions and Responses API calls are sanitized in flight, forwarded, and returned with violation headers describing what was caught. No SDK swap, no code refactor.

PYTHON
from openai import OpenAI

client = OpenAI(
    base_url="http://eko.internal:8080/v1",
    api_key=OPENAI_API_KEY,
)

Core Sanitization API

POST /v1/sanitize accepts arbitrary text and returns the sanitized string plus structured violation metadata — type, pattern, severity, matched value, and span. Use it in front of any LLM, in any language, in any architecture.

BASH
curl -X POST http://localhost:8080/v1/sanitize \
  -H "Content-Type: application/json" \
  -d '{"prompt": "My BVN is 22334455667", "mode": "redact"}'

What gets detected

Credentials & Secrets
  • API keys (OpenAI, Anthropic, Google, AWS, Azure)
  • JWTs and OAuth tokens
  • SSH private keys
  • Database connection strings (Postgres, MongoDB, MySQL)
  • Environment variables and generic secrets
Financial
  • Credit card numbers (Luhn-validated)
  • IBAN and SWIFT/BIC codes
  • CVV codes
  • Generic bank account numbers
African Identity & Finance
  • Nigerian BVN, NIN, NUBAN, mobile (+234)
  • Kenyan M-Pesa transaction codes, mobile (+254)
  • South African 13-digit national ID, mobile (+27)
  • Ghanaian mobile (+233)
Generic PII
  • Email addresses
  • Phone numbers (international formats)
Custom Patterns
  • Any regex declared in YAML
  • Per-pattern severity: BLOCK / WARN / LOG
  • Per-pattern action: redact or tokenize

Tokenize, don't just redact

Many flows lose value the moment a string becomes [REDACTED]. A support agent summarizing a case still needs to refer to “that customer” consistently across turns; a downstream system may need to round-trip a value back to the original record.

Ekō's tokenizer assigns a deterministic, opaque token per detected value within a session, stored in an encrypted Redis vault with optional Vault Transit envelope encryption. The same BVN seen twice in the same conversation gets the same token; a downstream service holding the session key can resolve it back.

Tokenize when context matters

Customer names, account numbers, phone numbers, emails, transaction amounts, vendor names. Tokenization keeps the workflow useful — the shape of the data is preserved.

Redact when exposure is unacceptable

API keys, passwords, database credentials, access tokens, private keys, webhook secrets. These should never leave the workflow at all.

Performance

Ekō is built to sit on the request path. Internal benchmarks on 4 vCPU / 8 GB show sub-5ms core API latency and sub-50ms end-to-end through the proxy at 1,000 req/s, with a memory footprint around 50 MB.

The repo includes the benchmark harness, baseline comparison, and memory-ceiling test so you can reproduce these numbers on your own hardware.

<5ms
Core API p95
<50ms
Proxy E2E p95
1k+
Req/s
~50MB
Memory

Where Ekō fits

Ekō exposes two interfaces — a drop-in OpenAI proxy and a core /v1/sanitize API — and that's deliberately the only choice your engineers have to make. What changes from one deployment to the next is who is calling it and where the prompt was generated.

Internal sanitization playground

A small web app fronted by /v1/sanitize that staff paste into before they paste into ChatGPT, Claude, or Gemini. Not a structural control, but it turns 'don't paste customer data into AI' from a policy line into a habit with a button.

Inside the AI products you ship

Banking assistants, KYC reviewers, fraud copilots, loan-eligibility chats. The team points its OpenAI SDK at Ekō and stops thinking about it. Sanitization becomes structural — a developer can't forget, because the egress path is Ekō.

In front of self-hosted chat UIs

assistant-ui, LibreChat, Open WebUI, AnythingLLM, Chatbox — anywhere an internal 'ChatGPT but inside our walls' has been stood up. One config line covers everyone behind it. Email and document AI plugins drop in the same way.

Slack, Teams, and browser middleware

A thin middleware intercepts @AI bot messages, calls /v1/sanitize, then forwards to the model — covering traffic no one ever architected. A browser extension hooking submit on chatgpt.com, claude.ai, and gemini.google.com offers the same defense without asking anyone to change behaviour.

Batch and pipeline jobs

Historical tickets going into a fine-tuning corpus. Airflow or Dagster jobs feeding PDFs to an LLM. Warehouse outbound syncs to analytics providers that run models on the data. Sanitize the corpus once on the way out.

Infrastructure-level egress control

Deploy Ekō as an Istio or Envoy sidecar, or as the only route to api.openai.com and friends, enforced by NetworkPolicy. No application can reach a public LLM without going through it, even if a developer hard-codes a URL.

Surfaces that matter for African deployments

Two surfaces generate the kind of unstructured, identifier-dense text the SLM sidecar was built for.

WhatsApp Business API bots

WhatsApp is a primary customer channel across Nigeria, Kenya, Ghana, and South Africa. Inbound messages are full of BVNs, NUBANs, M-Pesa codes, and ID numbers, often mid-sentence with no formatting cues. Sanitize the message body before it reaches the LLM that drafts the reply.

Call-centre and IVR transcripts

Customer service teams are increasingly piping call transcripts to LLMs for summarization, sentiment, or routing. Transcripts contain identifiers read aloud and rendered by ASR — exactly the high-volume, partly-mangled input where the regex layer drops recall and the contextual model earns its keep.

What's in the release

Bash
docker run -p 8080:8080 openray/eko:main-latest

Research preview, not a compliance product

This is a v0.1 release. Treat it accordingly.

Data-minimization layer

Not anonymization, not a compliance certification, and not the only control you should rely on for legal, regulatory, or irreversible decisions.

OpenAI proxy first

The OpenAI proxy is the only proxy implementation today. Anthropic and Google providers are on the roadmap; the core /v1/sanitize API works with any model in the meantime.

SLM sidecar is recall-oriented

It will over-redact in some cases. It is opt-in per request and falls back via a circuit breaker if unavailable.

Pair with surrounding controls

Production deployment should pair Ekō with representative local evaluation, access controls, audit logging, and human review where a missed detection could cause harm.

Build with us

Ekō is open source and built in public. If you're working on AI security, data sovereignty, or privacy infrastructure in Africa — we'd love to hear from you.

We are particularly interested in:

  • Real African-context prompts where Ekō missed a sensitive entity (false negatives) or flagged something benign (false positives)
  • Local data formats not yet covered — additional jurisdictions, ID schemes, financial identifiers
  • Integration patterns from production deployments — what worked, what required workarounds
  • OCR-derived text from Nigerian identity documents and bank statements, which exercises the SLM sidecar more than the regex layer
  • Hard-negative cases for the contextual detector

For enterprise support and custom pattern development, get in touch.

View on GitHub

Ekō uses Naija Privacy Filter for contextual PII detection. Check it out

Ekō (Yoruba: to guard, to protect) — because your data deserves protection.