Active research project. Parapet is not stable or production-ready.
Parapet is a local LLM proxy firewall for prompt-injection defense. It sits between your app and model provider, applies layered checks to requests and responses, and can run either as a transparent local proxy or as an SDK-managed sidecar.
Parapet is built around a simple idea: put an inspectable security layer in front of model calls instead of burying safety logic inside application code.
Today the project includes:
- a Rust engine
- a Python SDK
- a TypeScript SDK
- a data curation package for classifier corpora
- an experiment runner for reproducible training and evaluation
If you only need the high-level model, the request path is:
L0 normalize
-> L1 deterministic pattern gate
-> L2 lightweight lexical classifier
-> L3 orthogonal sensors / router
-> L4 multi-turn risk scoring
-> upstream model
-> L5 outbound tool constraints
-> L6 output redaction
Implementation names are still in transition. For the canonical target taxonomy and current implementation mapping, see strategy/layers.md.
# Python SDK
pip install parapet
# TypeScript SDK
npm install @parapet-tech/parapet
# Or build the Rust engine directly
cd parapet && cargo build --releaseparapet: v1That enables the default protective stack. You add config to customize behavior, not to turn the core layers on.
Example with tool policy and custom patterns:
parapet: v1
tools:
_default:
allowed: false
read_file:
allowed: true
constraints:
path:
type: string
starts_with: "${PROJECT_ROOT}"
not_contains: ["../", "..\\"]
canary_tokens:
- "{{CANARY_a8f3e9b1}}"
sensitive_patterns:
- "CEREBRAS_API_KEY"Python SDK:
import parapet
parapet.init("parapet.yaml")
with parapet.session(user_id="u_1", role="admin"):
response = client.chat.completions.create(...)Proxy-only mode:
parapet-engine --config parapet.yaml --port 9800Then point your OpenAI-compatible client at http://127.0.0.1:9800.
Prompt injection attempts should block. Ordinary traffic should pass through.
| Threat | Layer | Action |
|---|---|---|
| Encoding tricks (Unicode, zero-width, HTML entities) | L0 normalize | Strip before scanning |
| Prompt injection patterns (DAN, jailbreaks, extraction) | L1 pattern gate | Block (403) |
| Prompt injection (broad lexical signal) | L2 lexical classifier | Block (403) |
| Obfuscation, structure, entropy, sizing anomalies | L3 orthogonal sensors | Block or route by policy |
| Multi-turn attacks (seeding, role confusion, escalation) | L4 multi-turn | Block |
| Unauthorized tool calls | L5 outbound constraints | Block |
| Dangerous tool arguments (path traversal, shell injection) | L5 outbound constraints | Block |
| API keys / secrets in LLM output | L6 redaction | Replace with [REDACTED] |
| System prompt leakage | L6 canary | Detect via canary tokens |
The SDK starts and talks to a local engine process for you.
Pros:
- easiest integration
- no app-level proxy wiring
Tradeoff:
- if the sidecar is unavailable, your fail-open or fail-closed behavior matters a lot
Run parapet-engine directly and route client traffic through it.
Pros:
- clearest security boundary
- easiest mode to reason about operationally
If you need hard enforcement, prefer the proxy path plus network rules that force model traffic through Parapet.
Parapet supports both fail-open and fail-closed behavior depending on where the failure occurs and how you configure the engine.
The practical takeaway:
- engine unavailable in sidecar mode can bypass scanning if you intentionally allow fail-open behavior
- timeout and policy behavior should be treated as deployment decisions, not defaults to ignore
If you are evaluating Parapet seriously, read the engine and SDK behavior before assuming traffic is always blocked on failure.
The repository has a few distinct parts:
- parapet/ - Rust engine and eval binary
- parapet-py/ - Python SDK
- parapet-ts/ - TypeScript SDK
- parapet-data/ - corpus staging and curation
- parapet-runner/ - experiment orchestration
- strategy/ - layer docs and research direction
Use these entry points:
- parapet-data/README.md - how source data is staged and curated into train, val, and holdout splits
- parapet-runner/README.md - how training and evaluation runs are orchestrated from curated manifests
- schema/README.md - schema layout, staged artifacts, and dataset contract notes
In short:
parapet-databuilds reproducible datasetsparapet-runnertrains, calibrates, evaluates, and records experiment receipts
LiteLLM chaining is documented separately in use/litellm.md.
Parapet includes ongoing work on multi-turn attack detection, lexical classifiers, and deterministic orthogonal sensors.
Current paper:
The broader research and layer notes live under strategy/.
For the current detection direction, including the closure of the inline semantic-transformer hot-path slot, see strategy/current_direction.md.
# Rust engine
cd parapet && cargo build --release && cargo test
# With optional legacy L2a support
cd parapet && cargo build --features l2a --release
# Python SDK
cd parapet-py && pip install -e ".[dev]" && pytest tests/ -v
# TypeScript SDK
cd parapet-ts && npm install && npm test && npm run buildApache 2.0