Skip to main content

Cloakwall

PII/PHI redaction and tamper-evident audit logging for LiteLLM. Runs in-process — no sidecar container, no external endpoint, no model download.

LiteLLM's open-source guardrail framework supports custom guardrails plus Presidio, but Presidio means deploying and maintaining two extra containers, and audit logs, SIEM export and SSO sit behind the Enterprise licence. Cloakwall gives you redaction and a compliance-grade audit trail as one dependency-free plugin.

guardrails:
  - guardrail_name: cloakwall
    litellm_params:
      guardrail: cloakwall.guardrail.Cloakwall
      mode: pre_call
      default_on: true
      redaction_mode: mask
      audit_path: /var/log/cloakwall/audit.log

To mask PII in model responses as well, add redact_output: true and set mode: [pre_call, post_call].

user:  "Patient MRN: A1234567, email bob@clinic.org, card 4111111111111111"
model: "Patient <MRN>, email <EMAIL>, card <CARD>"

Install

pip install "cloakwall[litellm]"

LiteLLM refuses to start without a master key (an API key for the proxy itself), so set one, then point LiteLLM at a config that enables the guardrail, such as examples/config.yaml:

export LITELLM_MASTER_KEY="sk-$(openssl rand -hex 32)"
litellm --config config.yaml

Clients then call the proxy with Authorization: Bearer $LITELLM_MASTER_KEY.

Or run the container, which installs the same package from PyPI:

docker build -t cloakwall .
docker run -p 4000:4000 \
  -e LITELLM_MASTER_KEY="sk-$(openssl rand -hex 32)" \
  -e OPENAI_API_KEY=sk-... cloakwall

Run it on Linux in production. The audit log fsyncs every entry; that costs about 0.3 ms on Linux and about 100 ms on Windows (see Benchmarks).

Where it looks

Every request field LiteLLM forwards that can carry text, on every endpoint:

Request Fields redacted
Chat completions messages[].content (text parts), tool_calls[].function.arguments
Anthropic /v1/messages top-level system, text blocks, tool_use.input (every string inside), tool_result.content
Responses API input (string or items), function_call.arguments, function_call_output.output
Completions, image generation prompt
Embeddings input strings (token-id lists pass through)

Image, audio and file parts pass through untouched. Ids, roles, model names and function names are never rewritten.

With redact_output: true, responses are redacted too: chat content and tool-call arguments, text completions, and Anthropic content blocks. Streamed responses go through a stream redactor that holds back the last 64 characters (stream_holdback) and only releases text at a boundary no entity spans, so a card number split across two chunks is still caught. The cost is that streamed text reaches the client 64 characters later; none of it is dropped. Output redaction is off by default, because it changes what callers receive.

Three redaction modes

Mode alice@corp.com becomes Use when
mask <EMAIL> the model has no business seeing the field
hash <EMAIL:7f3a91c2> you need to correlate a user across requests without storing the value
partial <CARD:****1111> support staff need the tail

hash is deterministic under a local HMAC secret set with CLOAKWALL_SECRET. Same person, same token, every request. Without a secret one is generated per boot, so tokens are stable within a run only.

Audit trail

Every entry commits to the SHA-256 of the entry before it and carries a monotonic sequence number. The chain head is mirrored to a separate anchor file after every append, and pushed to your SIEM every anchor_every entries.

That combination catches all four tamper modes:

chain intact, 10 entries, anchor matches
line 2: entry altered after writing
line 3: chain break
truncated: anchor records 10 entries, log holds 6

The last one is why the anchor exists. A bare hash chain does not survive truncation — a prefix of a valid chain is itself a valid chain, so dropping the final entries verifies clean. The anchor still knows how many there should be.

An anchor on the same filesystem stops accidental truncation and a careless attacker. An anchor in your SIEM, under different access control, stops someone who can write to the pod. Pass a SIEM-retrieved anchor to verify(anchor=...) to check against a copy the log cannot reach.

The log records which entity types were found and how many. It never records the values that were redacted — an audit log that quotes the PII it scrubbed is a second copy of the problem.

SIEM export

export CLOAKWALL_SIEM=splunk          # splunk | datadog | elastic
export CLOAKWALL_SIEM_URL=https://splunk.internal:8088/services/collector
export CLOAKWALL_SIEM_TOKEN=...

Export runs on a worker thread. A slow or unreachable SIEM never adds latency to, or fails, an LLM request — the local log is the system of record.

Air-gapped

The core is pure standard library. Nothing in the redaction, audit or hashing path opens a socket, so it runs unchanged in an isolated cluster. Point LiteLLM at a local vLLM or Ollama endpoint and no data leaves your network at all.

Verify it yourself:

strace -f -e trace=connect python3 tests/test_cloakwall.py

Benchmarks

Measured, reproducible numbers are in BENCHMARKS.md: python3 benchmarks/bench.py. On a 2015 Core i3 under Linux, a clean request costs 0.05 ms and a request with PII, including its fsynced audit entry, about 1.8 ms.

Tests

python3 tests/test_cloakwall.py     # 76 tests, no pytest required

Limitations

Regex detection does not catch contextual PII — a person's name in free text, or a medical condition described in prose. If you need that, Presidio's NLP models are better and Cloakwall is not a replacement for them. What Cloakwall gives up in recall it gains in having no dependencies, no sidecar and no model to ship into an air-gapped environment.

Redaction is one-way. There is no un-redaction path, by design.

Status: working, tested, not yet run in production anywhere.

Security

Found a vulnerability, or a way PII gets past the redactor? Please report it privately; see SECURITY.md.

Licence

AGPL-3.0. Commercial licences for closed-source use are available.

Metadata

Release files for cloakwall 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cloakwall 0.1.1
File Size Uploaded Provenance Actions
cloakwall-0.1.1.tar.gz 36.9 kB Without provenance Details for cloakwall-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for cloakwall 0.1.1
File Interpreter ABI Platform Actions
cloakwall-0.1.1-py3-none-any.whl Python 3 none any Details for cloakwall-0.1.1-py3-none-any.whl

Total release size: 68.0 kB

Release files / cloakwall-0.1.1.tar.gz

Download URL cloakwall-0.1.1.tar.gz
Size 36.9 kB
Tags Source
SHA-256 checksum
How to use checksums
5ae0d952e86f111ea271bd5f20f8392b932c730a30f1c04fb3f5bc9dfd9c163c
BLAKE2b-256 checksum
How to use checksums
69e63615a8573a593ec77cfe9fa9801bcea6da86b95c41516de45ee9f358632c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release files / cloakwall-0.1.1-py3-none-any.whl

Download URL cloakwall-0.1.1-py3-none-any.whl
Size 31.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9d2f1501fb92b62778d9fd6e90240a9e43b8db68a68bc58009e691cd804e4cba
BLAKE2b-256 checksum
How to use checksums
50aeef52c701051950166ac278165622b35f231a83d090d759af3b67f9c6ea61
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Security for cloakwall 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page