English | Русский
SafeGate
Self-hosted AI security platform for LLM applications
Protect sensitive data · Stop prompt attacks · Control inference cost · Audit everything
Features · Quick start · What we detect · Examples · How it works · Docs
pip install safegate
Features
SafeGate sits between your app and the LLM (and around RAG embeddings). You enable only the stages you need.
| Capability | What you get | How to use |
|---|---|---|
| PII / secrets detection | 60+ entity types across identity, finance, health, network, vehicles, RU/US/UK IDs | SafeGate() / entity_types=[...] |
| Substitution or mask | Prompt: replace with dictionary fakes, or ***. Response: always *** (never fake values to the user) |
protection_mode="substitute" / "mask" |
| Prompt & response guards | Protect text before the LLM call; scan the answer for leaks; mask residual PII in the reply | protect_prompt → invoke → protect_response |
| Choose what to detect | Enable only the sensitive types you care about; everything else is ignored | entity_types=["email", "ssn", …] |
| EDOS guard (optional) | Score “cognitive bomb” prompts; strip wasteful instructions, route to a fallback LLM, or block | edos_enabled, edos_high_risk_action |
| Vector privacy (RAG) | ε-differential privacy noise + lineage obfuscation for embeddings | VectorPrivacyGuard / ContextGuard |
| Policies & industry packs | YAML rules, presets (health_hipaa, bank_ru, …), simulator |
preset="…", safegate policy catalog |
| Audit & SIEM | JSONL trail, CEF/ECS/CSV export, approval workflow | audit_path=… |
Prompt → PII guard → EDOS* → your LLM → response guard → user
RAG → context guard → vector privacy* → vector DB
* optional stages
Quick start
Install
pip install safegate
1) Protect text (no LLM required)
from safegate import SafeGate
guard = SafeGate(protection_mode="substitute") # or "mask"
session = guard.protect_prompt(
"Contact Alice at alice@company.com or +1 (415) 555-0100"
)
print(session.prompt_result.text)
# Contact … at <dictionary email> or <dictionary phone>
print(session.prompt_mappings)
2) Detect only selected types
from safegate import SafeGate, list_entity_types
# only email + phone + SSN
guard = SafeGate(entity_types=["email", "phone", "ssn"])
# or a whole domain
guard = SafeGate(entity_types=list_entity_types("financial"))
Full catalog: docs/SENSITIVE_ATTRIBUTES.md
CLI: safegate entities list --domains
3) Wire your real LLM
from safegate import SafeGate
from safegate.llm import OpenAIAdapter # or OllamaAdapter
guard = SafeGate(protection_mode="substitute")
session = (
guard.protect_prompt("My SSN is 123-45-6789")
.invoke(OpenAIAdapter(client, model="gpt-4o-mini"))
.protect_response()
)
print(session.result)
OpenAIAdapter works with any OpenAI-compatible API. OllamaAdapter is for local models.
About
MockLLM: it is a tiny stub that returns a fixed string. SafeGate uses it only in unit tests and offline demos so CI does not need API keys. It is not a production model — pass your own adapter toinvoke()/chat().
4) Optional: EDOS cost protection
guard = SafeGate(
edos_enabled=True, # set False to skip the stage
edos_high_risk_action="block", # or "route_fallback"
fallback_llm=OpenAIAdapter(cheap_client, model="gpt-4o-mini"),
)
5) Optional: RAG embedding privacy
from safegate import VectorPrivacyGuard
from safegate.guards import ContextChunk, ContextGuard
vector_guard = VectorPrivacyGuard(epsilon=1.0)
ctx = ContextGuard(vector_privacy=vector_guard)
result = ctx.protect_embeddings(
[ContextChunk(id="doc-1", text=text, embedding=vector)]
)
What we detect
Entities are grouped into domains. Enable a domain or pick individual types.
| Domain | Types (examples) |
|---|---|
| identity | full_name, date_of_birth, passport, us_passport, driver licenses |
| contact | email, phone, address, zip_code |
| national_ids | ssn, nino (UK), inn/snils (RU), ein, itin, employee_id |
| financial | credit_card, cvv, card_expiration, iban, swift_bic, salary, bank accounts |
| health | medical, member_id, insurance_id, npi, medicare_id |
| credentials | password, username, api_key |
| network | ip_address, mac_address, domain, social_handle (LinkedIn, @handles) |
| vehicles | vin, vehicle_registration, ru_license_plate, frequent_flyer |
| business | commercial_secret |
| attacks | prompt_injection, jailbreak (ThreatFeed) |
safegate entities list --domains
Complete tables with examples: docs/SENSITIVE_ATTRIBUTES.md
Examples
Sensitive values are found first, then either substituted from a built-in dictionary (prompt path) or masked with * (mask mode, and always on the LLM response).
Mode A — Dictionary substitution (prompt → LLM)
Fake values come from generated dictionary pools shipped with SafeGate (gdpr_fakes, default, industry packs). The vault maps each real value → one synthetic token for the session, so the LLM still sees realistic emails, phones, and IDs — not your real data.
guard = SafeGate(protection_mode="substitute")
# michael.carter@example.com → sofia.brennan@privacy.test (from dictionary)
# +1 (415) 555-0187 → +49 30 4829173 (from dictionary)
Mode B — Mask with asterisks
guard = SafeGate(protection_mode="mask")
# michael.carter@example.com → **************************
LLM response — always masked
Whatever comes back from the model is never filled with dictionary fakes and is never restored to real PII by default. Residual PII and echoed substitute tokens are replaced with *. Opt-in detokenize=True restores real values only when you explicitly need that legacy behaviour.
| Direction | Substitute mode | Mask mode |
|---|---|---|
| Prompt → LLM | Dictionary fakes | **** |
| LLM → user | **** (always) |
**** (always) |
Local UI to try both modes:
cd local-demo && python app.py
# http://127.0.0.1:8765/
How it works
flowchart LR
A[Input] --> B[Detectors — optional entity filter]
B --> C[Policy]
C -->|substitute / mask / block| D[Prompt guard]
D --> E[EDOS optional]
E --> F[Your LLM]
F --> G[Response guard — always mask]
G --> H[Output]
| Stage | Role |
|---|---|
| Detectors | Find sensitive values (filtered by entity_types if set) |
| Policy | Decide action per type: substitute · mask · block · remove |
| Prompt guard | Apply policy before the LLM call (dictionary or ****) |
| EDOS | Optional complexity scoring / strip / route / block |
| Response guard | Leak check; always mask residual PII and echoed tokens with **** |
| Audit | JSONL + SIEM fields including EDOS |
Examples
| Example | Use case |
|---|---|
| chatbot_demo.py | Chatbot with PII substitution |
| rag_demo.py | RAG context guard |
| mcp_demo.py | MCP tool filter |
| gateway_client.py | REST AI gateway |
| langchain_demo.py | LangChain handler |
Full list: examples/README.md
Industry packs
bank_ru · health_hipaa · gov_fz152 · retail_eu · fintech_us · insurance_us · saas_global · telecom_eu · education_us · energy_eu · legal_eu · logistics_eu
safegate policy catalog --format markdown
guard = SafeGate(preset="health_hipaa", region="us")
Documentation
| Doc | Contents |
|---|---|
| SENSITIVE_ATTRIBUTES.md | Full entity catalog + how to select types |
| INSTALL.md | Install / Docker |
| COMPARISON.md | vs Presidio / LLM Guard |
| PRODUCT_ROADMAP.md | Platform roadmap |
Contributing
SafeGate is open source (MIT).
git clone https://github.com/patonkikh/SafeGate.git
cd SafeGate
python -m pip install -e ".[dev]"
pytest -v
| Issues | github.com/patonkikh/SafeGate/issues |
| Guidelines | CONTRIBUTING.md |
| Security | SECURITY.md |
License
Metadata
Release files for safegate 2.0.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 |
|---|---|---|---|---|
| safegate-2.0.0.tar.gz | 128.5 kB | Without provenance | Details for safegate-2.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| safegate-2.0.0-py3-none-any.whl | Python 3 | none | any | Details for safegate-2.0.0-py3-none-any.whl |
Total release size: 277.0 kB
Release files / safegate-2.0.0.tar.gz
| Download URL | safegate-2.0.0.tar.gz |
|---|---|
| Size | 128.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
394efe941d15da63a645ff61898552ff60bfdc472792960df549cb4e128c7743
|
|
BLAKE2b-256 checksum How to use checksums |
c3b51e6e2eaec277a0ede4e6d9bfe97829d50a9692031f9e35e4c183f4eb2994
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.0
|
Release files / safegate-2.0.0-py3-none-any.whl
| Download URL | safegate-2.0.0-py3-none-any.whl |
|---|---|
| Size | 148.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f3f98ab81ab463be9728500a7b3eb09d234acc41c715bf4b0ad7f8fc344b5c9a
|
|
BLAKE2b-256 checksum How to use checksums |
916c70f68315c0685131dba6ab7270bb3f58b9ea1d4f52e1d452cd03dd042240
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.0
|
Security for safegate 2.0.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.