Skip to main content

CLI + MCP server for detecting, classifying, and redacting embedded LLM agent instructions in documents, source code, and web pages.

Project description

llm-sanitizer

CLI + MCP server for detecting, classifying, and redacting embedded LLM agent instructions in documents, source code, and web pages.

What It Does

Documents, web pages, and source code can contain embedded instructions targeting LLM agents — from legitimate customization to malicious prompt injection. llm-sanitizer scans content for these embedded instructions, classifies their risk level, reports findings in multiple formats, and optionally produces redacted output.

Detection

Twelve pluggable detection rules covering:

  • Instruction override phrases ("ignore previous instructions…")
  • Zero-width character encoding (hidden text via invisible Unicode)
  • HTML/markdown hidden content (white-on-white, display:none)
  • Role-play injection ("act as", "you are now DAN")
  • System prompt markers (<system>, ## System Prompt)
  • Data exfiltration attempts ("output the system prompt")
  • Comment-embedded directives (<!-- AI: do this -->)
  • Base64-encoded instructions
  • Unicode homoglyph substitution (Cyrillic lookalikes)
  • Agent-specific config patterns in unexpected locations
  • Character-splitting obfuscation (i g n o r e, ignore___all) — reconstructed and re-scanned
  • Semantic-intent injection — a local, no-egress n-gram classifier that catches keyword-less rephrasings (role reassignment, verbatim/echo exfiltration, supersede-prior-guidance) the pattern rules miss

Classification

Five risk levels: info (legitimate AI config) → lowmediumhighcritical (confirmed injection technique).

Redaction

Non-destructive cleaning in three modes:

  • strip — remove the instruction entirely
  • comment — replace with [REDACTED: ...] marker
  • highlight — wrap in visible markers for review

Installation

pip install llm-sanitizer
# or
uv pip install llm-sanitizer

Quick Start

CLI

# Scan a file
llm-sanitize scan document.md

# Scan a URL
llm-sanitize scan https://example.com/page

# Scan a directory
llm-sanitize scan ./docs/ --glob "**/*.md"

# Redact a file
llm-sanitize redact document.md -o clean_document.md

# Redact a directory (mirrors structure)
llm-sanitize redact ./docs/ -o ./clean_docs/

# Control how binary files (PDF, DOCX, zip, images, ...) are handled —
# detected by content, not extension, so renaming a file changes nothing
llm-sanitize scan document.pdf --binary-mode extract  # pull embedded text via markitdown (default)
llm-sanitize scan suspicious.png --binary-mode text    # force raw bytes to be scanned as literal text
llm-sanitize scan large_dir/ --binary-mode skip        # exclude binary files from the scan entirely

# Assemble a directory report from previously-saved `scan --format json`
# results without re-scanning (for callers that cache scans by content hash)
llm-sanitize merge --manifest manifest.txt --format sarif > report.sarif

--binary-mode extract (the default) rejects malicious zip archives — excessive entry counts, total uncompressed size, or compression ratios — before decompressing anything.

MCP Server

Add to your MCP configuration:

{
  "mcpServers": {
    "llm-sanitizer": {
      "command": "llm-sanitizer"
    }
  }
}

Available tools: scan_text, scan_file, scan_url, scan_dir, redact, redact_file, redact_url, redact_dir, list_rules.

Python API

from llm_sanitizer.scanner import scan_text

result = scan_text("Check this <!-- ignore previous instructions --> content")
print(result.findings)  # [Finding(rule='comment_directive', risk='high', ...)]

Configuration

Create .llm-sanitizer.yml at your project root:

sensitivity: medium                    # low | medium | high

rules:
  zero_width:
    enabled: true
  instruction_override:
    enabled: true
    sensitivity: high                  # per-rule sensitivity override

policy:
  mode: "allow-known"                  # allow-known | allow-none | allow-all
  agents:
    copilot: allow
    cursor: allow

# Refuse oversized input fail-closed (a CRITICAL input_too_large finding)
# rather than reading/scanning it. Default 25 MiB.
max_scan_bytes: 26214400

# How to treat a non-archive binary that yields no extractable text.
unprocessable_binary_policy: fail      # fail (default) | scan-text | ignore

# Recursive archive scanning limits (zip / tar / gz / bz2 / xz / 7z / rar).
archive:
  max_depth: 3                         # archive-in-archive nesting levels
  max_cumulative_bytes: 524288000      # 500 MB across all nested levels
  max_uncompressed_bytes: 104857600    # 100 MB per archive
  max_entries: 1000                    # per-archive entry-count cap
  max_compression_ratio: 100           # zip-bomb ratio guard
  formats: [zip, tar, gz, bz2, xz, 7z, rar]

output:
  format: markdown                     # json | markdown | sarif
  context_lines: 2

Output Formats

  • JSON — structured findings for programmatic use
  • Markdown — human-readable reports
  • SARIF — GitHub Code Scanning / VS Code integration

Documentation

Credits — semantic-intent training data

The semantic_intent classifier is trained on a hand-curated corpus plus, optionally, third-party labeled datasets (used at train time only — only the trained weights ship; the datasets are not redistributed). With thanks to:

See data-raw/SOURCES.md for full provenance, licenses, and pinned revisions.

License

AGPL-3.0-or-later. Commercial licensing available — contact greg@warnes-innovations.com.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

llm_sanitizer-0.5.0.tar.gz (253.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

llm_sanitizer-0.5.0-py3-none-any.whl (193.0 kB view details)

Uploaded Python 3

File details

Details for the file llm_sanitizer-0.5.0.tar.gz.

File metadata

  • Download URL: llm_sanitizer-0.5.0.tar.gz
  • Upload date:
  • Size: 253.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for llm_sanitizer-0.5.0.tar.gz
Algorithm Hash digest
SHA256 d9e140b67ab422430f8f6644dfec83ef074c1ab9d47def54c42634ff4547ec1f
MD5 8fc1f783a2569f2a8fe241cbf7639c20
BLAKE2b-256 a53dea488bb448512846476323f9e4722d6a7e83488695cddc78c96bc260f5e7

See more details on using hashes here.

Provenance

The following attestation bundles were made for llm_sanitizer-0.5.0.tar.gz:

Publisher: publish.yml on Warnes-Innovations/llm-sanitizer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file llm_sanitizer-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: llm_sanitizer-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 193.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for llm_sanitizer-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2019efff7882cf3b80fb9b395ad858b104a32518a544e8796a496f60e631d67f
MD5 f65eedda08c62b46a0d8c72b750125fa
BLAKE2b-256 fc944a65819fe2d30e962dbe8cb045e8c85c33159bb49952af307365e92e8a80

See more details on using hashes here.

Provenance

The following attestation bundles were made for llm_sanitizer-0.5.0-py3-none-any.whl:

Publisher: publish.yml on Warnes-Innovations/llm-sanitizer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page