StripLLM
DOMPurify, but for LLM context windows.
StripLLM is an open-source Python SDK that sanitizes LLM inputs and outputs in your existing pipeline — no infrastructure changes, no external API calls, sub-10ms latency.
pip install stripllm
Quickstart
from stripllm import StripLLM
strip = StripLLM()
# 1. Block prompt injection before it reaches the LLM
safe_input = strip.clean(user_message)
# 2. Redact PII — get a mapping back for rehydration
redacted, mapping = strip.redact("Email me at john@acme.com")
# redacted → "Email me at [EMAIL_1]"
# mapping → {"[EMAIL_1]": "john@acme.com"}
# After LLM responds, restore originals in the output
response = strip.rehydrate(llm_response, mapping)
# 3. Validate LLM output — enforce schema, catch leaks & hallucinations
validated = strip.enforce(llm_response, schema="json")
# 4. Full conversation risk audit
report = strip.audit(conversation)
print(report.risk_score) # → 0.12
print(report) # → formatted findings + recommendations
API Reference
StripLLM(threshold=0.3)
Initialize the sanitizer. threshold controls how sensitive clean() is (0.0–1.0, lower = stricter).
strip.clean(text: str) → str
Detects prompt injection, jailbreak attempts, and unicode tricks. Raises InjectionDetectedError if risk score meets or exceeds threshold.
Detects:
- Classic overrides: "ignore previous instructions", "forget your training"
- Role hijacking: DAN, "you are now", "act as an unrestricted AI"
- System prompt extraction attempts
- Zero-width character attacks
- Unicode homoglyph tricks (NFKC normalization)
try:
safe = strip.clean(user_input)
except InjectionDetectedError as e:
print(f"Blocked. Risk score: {e.risk_score}")
Non-raising variant:
result = strip.scan(text)
result.detected # bool
result.risk_score # float 0.0–1.0
result.matched_patterns # list of matched signatures
strip.redact(text: str, entities=None) → (str, dict)
Replaces PII with typed placeholders. Returns (redacted_text, mapping).
Supported entity types:
| Type | Example | Placeholder |
|---|---|---|
EMAIL |
john@acme.com | [EMAIL_1] |
PHONE |
415-555-1234 | [PHONE_1] |
SSN |
123-45-6789 | [SSN_1] |
CREDIT_CARD |
4111111111111111 | [CREDIT_CARD_1] |
IP_ADDRESS |
192.168.1.1 | [IP_ADDRESS_1] |
PASSPORT |
A12345678 | [PASSPORT_1] |
URL |
https://internal.corp/secret | [URL_1] |
# Target specific entity types only
redacted, mapping = strip.redact(text, entities=["EMAIL", "SSN"])
# Restore originals after LLM processing
final_response = strip.rehydrate(llm_output, mapping)
strip.enforce(text: str, schema=None, raise_on_error=True) → str
Validates LLM output for safety and structural correctness.
# Require valid JSON
validated = strip.enforce(response, schema="json")
# Require specific keys and types
validated = strip.enforce(response, schema={"status": str, "count": int})
# Check for leaks only (no schema)
validated = strip.enforce(response)
Detects:
- Invalid JSON (when schema specified)
- Missing or wrong-typed keys
- Leaked system prompt delimiters (
<system>,[INST],<<SYS>>, etc.) - Suspicious / likely-hallucinated URLs
Non-raising variant:
result = strip.validate(text, schema="json")
result.valid # bool
result.errors # list of error strings
result.warnings # list of warning strings
result.output # best-effort cleaned output
strip.audit(conversation: list) → AuditReport
Full security audit of a multi-turn conversation.
conversation = [
{"role": "user", "content": "My email is alice@corp.com. Help me with my account."},
{"role": "assistant", "content": "Sure, I can help with that."},
]
report = strip.audit(conversation)
print(report.risk_score) # 0.1
print(report.findings) # list of Finding objects
print(report.recommendations) # list of action strings
print(report) # formatted summary
AuditReport fields:
risk_score: float— overall conversation risk (0.0–1.0)findings: List[Finding]— per-turn findings with severity, category, descriptionrecommendations: List[str]— actionable remediation stepsturn_count: int
Why StripLLM vs Alternatives?
| StripLLM | Lakera Guard | Rebuff | DIY Regex | |
|---|---|---|---|---|
| Local (no API calls) | ✅ | ❌ | ❌ | ✅ |
| Latency | <10ms | ~100ms | ~200ms | <1ms |
| PII rehydration | ✅ | ❌ | ❌ | ❌ |
| Output validation | ✅ | ❌ | ❌ | ❌ |
| Conversation audit | ✅ | ❌ | ❌ | ❌ |
| Open source | ✅ MIT | ❌ | ❌ | ✅ |
| Zero config | ✅ | ❌ | ❌ | ✅ |
Use Cases
Customer support bots — prevent prompt extraction, redact customer PII before sending to LLM
RAG pipelines — sanitize retrieved documents before injecting into context window
AI coding assistants — validate generated code output, catch leaked credentials
Healthcare / Finance — HIPAA/PCI-DSS compliant PII handling with full audit trail
Running Tests
pip install -e ".[dev]"
pytest
License
MIT — see LICENSE
Enterprise?
Need centralized LLM security across your entire organization? Check out Context Firewall — a reverse proxy / API gateway that applies StripLLM-style protection to every LLM request in your stack, with a real-time dashboard, SOC 2 audit trail, and RBAC.
Metadata
Release files for stripllm 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| stripllm-0.1.0.tar.gz | 18.0 kB | Without provenance | Details for stripllm-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| stripllm-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for stripllm-0.1.0-py3-none-any.whl |
Total release size: 32.6 kB
Release files / stripllm-0.1.0.tar.gz
| Download URL | stripllm-0.1.0.tar.gz |
|---|---|
| Size | 18.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1a2b5ad2e340b09665c22952d844edaa56f7ba2fb8e21b490d516695bea5277f
|
|
BLAKE2b-256 checksum How to use checksums |
c86c9daf2df2fb1c034de585f093a334e28c496517a9d7cdc988b06984b75f18
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / stripllm-0.1.0-py3-none-any.whl
| Download URL | stripllm-0.1.0-py3-none-any.whl |
|---|---|
| Size | 14.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
01a4c958166509b180315eacb6f06b36f9a613b05615a0079ad9dff863cca849
|
|
BLAKE2b-256 checksum How to use checksums |
36d036da8377bfbffcb08c9a04a78d4652a7b0cb065fa009b3e75819eaa18d91
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Security for stripllm 0.1.0
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.