[](https://github.com/sgasser/llm-shield/actions/workflows/ci.yml)
[](LICENSE)
-Privacy proxy for LLMs. Masks personal data before sending to your provider (OpenAI, Azure, etc.), or routes sensitive requests to local LLM.
+Privacy proxy for LLMs. Masks personal data and secrets / credentials before sending to your provider (OpenAI, Azure, etc.), or routes sensitive requests to local LLM.
<img src="docs/dashboard.png" width="100%" alt="LLM-Shield Dashboard">
## What It Detects
-| Type | Examples |
-|------|----------|
-| Names | John Smith, Sarah Miller |
-| Emails | john@acme.com |
-| Phone numbers | +1 555 123 4567 |
-| Credit cards | 4111-1111-1111-1111 |
-| IBANs | DE89 3704 0044 0532 0130 00 |
-| IP addresses | 192.168.1.1 |
-| Locations | New York, Berlin |
+### PII (Personal Identifiable Information)
+
+| Type | Examples |
+| ------------- | --------------------------- |
+| Names | John Smith, Sarah Miller |
+| Emails | john@acme.com |
+| Phone numbers | +1 555 123 4567 |
+| Credit cards | 4111-1111-1111-1111 |
+| IBANs | DE89 3704 0044 0532 0130 00 |
+| IP addresses | 192.168.1.1 |
+| Locations | New York, Berlin |
Additional entity types can be enabled: `US_SSN`, `US_PASSPORT`, `CRYPTO`, `NRP`, `MEDICAL_LICENSE`, `URL`.
+### Secrets (Secrets Shield)
+
+| Type | Examples |
+| -------------------- | --------------------------------------------------------------------------------------------------------- |
+| OpenSSH private keys | `-----BEGIN OPENSSH PRIVATE KEY-----` |
+| PEM private keys | `-----BEGIN RSA PRIVATE KEY-----`, `-----BEGIN PRIVATE KEY-----`, `-----BEGIN ENCRYPTED PRIVATE KEY-----` |
+
+Secrets detection runs **before** PII detection and blocks requests by default (configurable). Detected secrets are never logged in their original form.
+
**Languages**: 24 languages supported (configurable at build time). Auto-detected per request.
Powered by [Microsoft Presidio](https://microsoft.github.io/presidio/).
`ca`, `zh`, `hr`, `da`, `nl`, `en`, `fi`, `fr`, `de`, `el`, `it`, `ja`, `ko`, `lt`, `mk`, `nb`, `pl`, `pt`, `ro`, `ru`, `sl`, `es`, `sv`, `uk`
**Language Fallback Behavior:**
+
- Text language is auto-detected for each request
- If detected language is not installed, falls back to `fallback_language` (default: `en`)
- Dashboard shows fallback as `FR→EN` when French text is detected but only English is installed
type: openai
base_url: https://api.openai.com/v1
masking:
- placeholder_format: "<{TYPE}_{N}>" # Format for masked values
- show_markers: false # Add visual markers to unmasked values
+ placeholder_format: "<{TYPE}_{N}>" # Format for masked values
+ show_markers: false # Add visual markers to unmasked values
```
**Route mode:**
local:
type: ollama
base_url: http://localhost:11434
- model: llama3.2 # Model for all local requests
+ model: llama3.2 # Model for all local requests
routing:
default: upstream
on_pii_detected: local
```
-**Customize detection:**
+**Customize PII detection:**
```yaml
pii_detection:
- score_threshold: 0.7 # Confidence (0.0 - 1.0)
- entities: # What to detect
+ score_threshold: 0.7 # Confidence (0.0 - 1.0)
+ entities: # What to detect
- PERSON
- EMAIL_ADDRESS
- PHONE_NUMBER
- IBAN_CODE
```
+**Secrets detection (Secrets Shield):**
+
+```yaml
+secrets_detection:
+ enabled: true # Enable secrets detection
+ action: block # block | redact | route_local
+ entities: # Secret types to detect
+ - OPENSSH_PRIVATE_KEY
+ - PEM_PRIVATE_KEY
+ max_scan_chars: 200000 # Performance limit (0 = no limit)
+ log_detected_types: true # Log types (never logs content)
+```
+
+- **block** (default): Returns HTTP 422 error, request never reaches LLM
+- **redact**: Replaces secrets with placeholders (Phase 2)
+- **route_local**: Routes to local provider when secrets detected (Phase 2, requires route mode)
+
**Logging options:**
```yaml
logging:
database: ./data/llm-shield.db
- retention_days: 30 # 0 = keep forever
- log_content: false # Log full request/response
- log_masked_content: true # Log masked content for dashboard
+ retention_days: 30 # 0 = keep forever
+ log_content: false # Log full request/response
+ log_masked_content: true # Log masked content for dashboard
```
**Dashboard authentication:**
**Endpoints:**
-| Endpoint | Description |
-|----------|-------------|
+| Endpoint | Description |
+| ---------------------------------- | ---------------------------- |
| `POST /openai/v1/chat/completions` | Chat API (OpenAI-compatible) |
-| `GET /openai/v1/models` | List models |
-| `GET /dashboard` | Monitoring UI |
-| `GET /dashboard/api/logs` | Request logs (JSON) |
-| `GET /dashboard/api/stats` | Statistics (JSON) |
-| `GET /health` | Health check |
-| `GET /info` | Current configuration |
+| `GET /openai/v1/models` | List models |
+| `GET /dashboard` | Monitoring UI |
+| `GET /dashboard/api/logs` | Request logs (JSON) |
+| `GET /dashboard/api/stats` | Statistics (JSON) |
+| `GET /health` | Health check |
+| `GET /info` | Current configuration |
**Response headers:**
-| Header | Value |
-|--------|-------|
-| `X-Request-ID` | Request identifier (forwarded or generated) |
-| `X-LLM-Shield-Mode` | `route` / `mask` |
-| `X-LLM-Shield-PII-Detected` | `true` / `false` |
-| `X-LLM-Shield-PII-Masked` | `true` / `false` (mask mode) |
-| `X-LLM-Shield-Provider` | `upstream` / `local` |
-| `X-LLM-Shield-Language` | Detected language code |
-| `X-LLM-Shield-Language-Fallback` | `true` if fallback was used |
+| Header | Value |
+| -------------------------------- | ------------------------------------------------------------------------------------------- |
+| `X-Request-ID` | Request identifier (forwarded or generated) |
+| `X-LLM-Shield-Mode` | `route` / `mask` |
+| `X-LLM-Shield-PII-Detected` | `true` / `false` |
+| `X-LLM-Shield-PII-Masked` | `true` / `false` (mask mode) |
+| `X-LLM-Shield-Provider` | `upstream` / `local` |
+| `X-LLM-Shield-Language` | Detected language code |
+| `X-LLM-Shield-Language-Fallback` | `true` if fallback was used |
+| `X-LLM-Shield-Secrets-Detected` | `true` if secrets detected |
+| `X-LLM-Shield-Secrets-Types` | Comma-separated list of detected secret types (e.g., `OPENSSH_PRIVATE_KEY,PEM_PRIVATE_KEY`) |
## Development