From be83a804aee94e0b9772b56f230efe703e6cba69 Mon Sep 17 00:00:00 2001 From: tyagian Date: Sat, 2 May 2026 22:38:37 -0400 Subject: [PATCH 1/2] improve parsing data --- sentinelguard/scanners/prompt/secrets.py | 47 +++++++++++++++++++++--- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/sentinelguard/scanners/prompt/secrets.py b/sentinelguard/scanners/prompt/secrets.py index 4c5443c..8e061b4 100644 --- a/sentinelguard/scanners/prompt/secrets.py +++ b/sentinelguard/scanners/prompt/secrets.py @@ -148,20 +148,44 @@ def __init__( def scan(self, text: str, **kwargs: Any) -> ScanResult: found_secrets: Dict[str, int] = {} + secret_matches: List[Dict[str, Any]] = [] # position + value info for sanitization # Method 1: Vendor-specific patterns for secret_type, pattern in VENDOR_PATTERNS.items(): if self.secret_types and secret_type not in self.secret_types: continue - if pattern.findall(text): - found_secrets[secret_type] = len(pattern.findall(text)) + for match in pattern.finditer(text): + found_secrets[secret_type] = found_secrets.get(secret_type, 0) + 1 + secret_matches.append({ + "type": secret_type, + "start": match.start(), + "end": match.end(), + "text": match.group(0), + }) # Method 2: Generic keyword patterns for secret_type, pattern in KEYWORD_PATTERNS.items(): if self.secret_types and secret_type not in self.secret_types: continue - if pattern.findall(text): - found_secrets[secret_type] = len(pattern.findall(text)) + for match in pattern.finditer(text): + found_secrets[secret_type] = found_secrets.get(secret_type, 0) + 1 + # For keyword patterns, the value is in group(1) or group(2) + try: + value = match.group(2) if match.lastindex and match.lastindex >= 2 else match.group(1) + val_start = match.start() + match.group(0).index(value) + secret_matches.append({ + "type": secret_type, + "start": val_start, + "end": val_start + len(value), + "text": value, + }) + except (IndexError, ValueError): + secret_matches.append({ + "type": secret_type, + "start": match.start(), + "end": match.end(), + "text": match.group(0), + }) # Method 3: High-entropy string detection if self.detect_entropy: @@ -171,6 +195,12 @@ def scan(self, text: str, **kwargs: Any) -> ScanResult: continue if _shannon_entropy(candidate) > HEX_ENTROPY_THRESHOLD: found_secrets["high_entropy_hex"] = found_secrets.get("high_entropy_hex", 0) + 1 + secret_matches.append({ + "type": "high_entropy_hex", + "start": match.start(1), + "end": match.end(1), + "text": candidate, + }) for match in _BASE64_CANDIDATE.finditer(text): candidate = match.group(1) @@ -178,13 +208,19 @@ def scan(self, text: str, **kwargs: Any) -> ScanResult: continue if len(candidate) >= 20 and _shannon_entropy(candidate) > BASE64_ENTROPY_THRESHOLD: found_secrets["high_entropy_base64"] = found_secrets.get("high_entropy_base64", 0) + 1 + secret_matches.append({ + "type": "high_entropy_base64", + "start": match.start(1), + "end": match.end(1), + "text": candidate, + }) if not found_secrets: return ScanResult( is_valid=True, score=0.0, risk_level=RiskLevel.LOW, - details={"secrets_found": {}}, + details={"secrets_found": {}, "secret_matches": []}, ) max_score = 0.0 @@ -206,5 +242,6 @@ def scan(self, text: str, **kwargs: Any) -> ScanResult: "secrets_found": found_secrets, "secret_types": list(found_secrets.keys()), "total_secrets": sum(found_secrets.values()), + "secret_matches": secret_matches, }, ) From 933c0b8c3e37a584470eb8e7bded29f52579b25c Mon Sep 17 00:00:00 2001 From: tyagian Date: Sat, 2 May 2026 22:50:07 -0400 Subject: [PATCH 2/2] fix --- README.md | 336 +------------------------------------- pyproject.toml | 2 +- sentinelguard/__init__.py | 2 +- 3 files changed, 10 insertions(+), 330 deletions(-) diff --git a/README.md b/README.md index 9ef459e..afb9039 100644 --- a/README.md +++ b/README.md @@ -7,22 +7,17 @@ SentinelGuard provides 36 security scanners, enterprise-grade PII detection, adv ## Features -- **19 Prompt Scanners** - Injection detection, PII, toxicity, secrets, supply chain, data poisoning, and more -- **17 Output Scanners** - Bias, data leakage, XSS/SQLi sanitization, excessive agency, system prompt leakage, misinformation, and more -- **OWASP LLM Top 10 (2025)** - Full compliance with built-in compliance checker and reporting -- **Presidio PII Integration** - Enterprise-grade detection with 50+ entity types -- **Adversarial Detection** - Multi-method attack detection (perturbation, semantic, statistical, embedding) -- **Embedding Guardrails** - Semantic topic enforcement using vector embeddings -- **FastAPI Server** - REST API for integration with any stack -- **CLI Tool** - Command-line scanning and configuration -- **Async Support** - Full async/await support for high-performance applications -- **Configuration System** - YAML/JSON configs with presets (minimal, standard, strict) -- **Jupyter Notebooks** - Interactive examples for all features +- **19 Prompt Scanners** — Injection detection, PII, toxicity, secrets, supply chain, data poisoning, and more +- **17 Output Scanners** — Bias, data leakage, XSS/SQLi sanitization, excessive agency, system prompt leakage, misinformation, and more +- **OWASP LLM Top 10 (2025)** — Full compliance with built-in compliance checker and reporting +- **PII Detection & Anonymization** — Enterprise-grade detection with 30+ entity types and multiple anonymization strategies +- **Adversarial Detection** — Multi-method attack detection (perturbation, semantic, statistical, embedding) +- **Secrets Detection** — API keys, tokens, passwords, credentials via pattern matching and entropy analysis +- **Async Support** — Full async/await support for high-performance applications +- **Configuration System** — YAML/JSON configs with presets (minimal, standard, strict) ## OWASP LLM Top 10 (2025) Coverage -SentinelGuard provides **complete coverage** of all OWASP LLM Top 10 vulnerability categories: - | OWASP ID | Vulnerability | Scanners | Risk Level | |----------|--------------|----------|------------| | **LLM01** | Prompt Injection | `prompt_injection`, `invisible_text`, `ban_code` | CRITICAL | @@ -55,21 +50,7 @@ print(report.summary()) ## Installation ```bash -# Basic pip install sentinelguard - -# All features -pip install sentinelguard[all] - -# Specific features -pip install sentinelguard[pii] # Presidio PII detection -pip install sentinelguard[adversarial] # Adversarial detection models -pip install sentinelguard[advanced] # Embeddings + transformers -pip install sentinelguard[api] # FastAPI server -pip install sentinelguard[monitoring] # OpenTelemetry metrics - -# spaCy model for PII (if using Presidio) -python -m spacy download en_core_web_sm ``` ## Quick Start @@ -133,307 +114,6 @@ config = GuardConfig( guard = SentinelGuard(config=config) ``` -### Builder Pattern - -```python -guard = SentinelGuard() -guard.use("prompt_injection", on="prompt", threshold=0.7) -guard.use("pii", on="both", threshold=0.5) -guard.use("toxicity", on="prompt", threshold=0.7) -guard.use("bias", on="output", threshold=0.5) -guard.use("data_leakage", on="output", threshold=0.5) -guard.use("output_sanitization", on="output", threshold=0.3) -``` - -### Full Pipeline - -```python -guard = SentinelGuard.minimal() - -# Scan input -prompt_result = guard.scan_prompt(user_input) -if not prompt_result.is_valid: - return "Input blocked" - -# Call your LLM -llm_output = call_llm(user_input) - -# Scan output -output_result = guard.scan_output(llm_output, prompt=user_input) -if not output_result.is_valid: - return "Output blocked" - -return llm_output -``` - -### YAML Configuration - -```yaml -# sentinelguard.yaml -mode: strict -fail_fast: true -prompt_scanners: - prompt_injection: - enabled: true - threshold: 0.5 - pii: - enabled: true - threshold: 0.3 - supply_chain: - enabled: true - threshold: 0.4 - data_poisoning: - enabled: true - threshold: 0.4 -output_scanners: - data_leakage: - enabled: true - threshold: 0.5 - output_sanitization: - enabled: true - threshold: 0.3 - excessive_agency: - enabled: true - threshold: 0.4 -``` - -```python -guard = SentinelGuard.from_config("sentinelguard.yaml") -``` - -## Scanners - -### Prompt Scanners (19) - -| Scanner | OWASP | Description | -|---------|-------|-------------| -| `prompt_injection` | LLM01 | Detects injection attempts (patterns, heuristics, optional model) | -| `pii` | LLM02 | Detects PII with Presidio integration (50+ entity types) | -| `secrets` | LLM02 | Finds API keys, tokens, passwords (12+ pattern types) | -| `toxicity` | LLM04 | Identifies toxic/hateful content | -| `gibberish` | - | Detects nonsense/random text | -| `invisible_text` | LLM01 | Finds zero-width Unicode and hidden characters | -| `code` | - | Detects code snippets (Python, JS, SQL, Shell, etc.) | -| `ban_topics` | - | Blocks specific topics via keyword matching | -| `ban_competitors` | - | Prevents competitor brand mentions | -| `ban_substrings` | - | Blocks specific phrases/substrings | -| `ban_code` | LLM01,06 | Prevents code injection (eval, exec, system) | -| `anonymize` | LLM02 | Detects and replaces PII with anonymized tokens | -| `language` | - | Detects language, enforces allowed languages | -| `regex` | - | Custom regex pattern matching (allow/deny) | -| `sentiment` | - | Analyzes sentiment, blocks negative content | -| `token_limit` | LLM10 | Enforces token/character limits | -| `unbounded_consumption` | LLM10 | Detects resource exhaustion attacks (DoS, recursion) | -| `supply_chain` | LLM03 | Detects untrusted models, malicious packages, deserialization | -| `data_poisoning` | LLM04 | Detects training data injection, backdoors, knowledge corruption | - -### Output Scanners (17) - -| Scanner | OWASP | Description | -|---------|-------|-------------| -| `bias` | - | Detects biased language (gender, racial, age, etc.) | -| `relevance` | - | Checks prompt-output relevance via keyword overlap | -| `factual_consistency` | LLM09 | Detects internal contradictions | -| `sensitive` | LLM07 | Finds leaked system info (paths, IPs, prompts) | -| `malicious_urls` | LLM05 | Detects phishing/suspicious URLs | -| `no_refusal` | - | Detects LLM refusal patterns | -| `reading_time` | - | Estimates and limits reading time | -| `json` | LLM05 | Validates JSON structure and required fields | -| `language_same` | - | Ensures output language matches prompt | -| `url_reachability` | - | Checks if URLs are reachable | -| `deanonymize` | LLM02 | Reverses anonymization using mapping | -| `data_leakage` | LLM02 | Detects PII, financial, medical, credential exposure | -| `excessive_agency` | LLM06 | Detects unauthorized code execution, file ops, privilege escalation | -| `misinformation` | LLM09 | Detects hallucination, fake citations, fabricated statistics | -| `output_sanitization` | LLM05 | Detects XSS, SQL injection, command injection, SSRF, path traversal | -| `system_prompt_leakage` | LLM07 | Detects system prompt echo, config leak, API key exposure | -| `vector_weakness` | LLM08 | Detects RAG poisoning, embedding manipulation, data extraction | - -## Advanced Features - -### PII Detection (Presidio) - -```python -from sentinelguard.pii import PIIDetector, PIIAnonymizer - -detector = PIIDetector( - language="en", - entities=["EMAIL", "PHONE", "CREDIT_CARD", "SSN"], - score_threshold=0.5, -) -entities = detector.detect("Email: john@example.com, SSN: 123-45-6789") - -anonymizer = PIIAnonymizer(default_strategy="replace") -result = anonymizer.anonymize(text, entities) -# "Email: , SSN: " -``` - -Strategies: `replace`, `mask`, `hash`, `redact`, `fake` - -### Adversarial Detection - -```python -from sentinelguard.adversarial import AdversarialDetector, AdversarialDefender - -detector = AdversarialDetector( - threshold=0.7, - config={"methods": ["perturbation", "semantic", "statistical"]}, -) -result = detector.detect(text, original=clean_text) - -defender = AdversarialDefender() -cleaned = defender.defend(adversarial_text) -``` - -### Embedding Guardrails - -```python -from sentinelguard.embeddings import EmbeddingGuardrail - -guardrail = EmbeddingGuardrail() -guardrail.add_allowed_topics({ - "support": ["How can I help?", "Order questions"], -}) -guardrail.add_banned_topics({ - "medical": ["Diagnose condition", "Medication advice"], -}) - -result = guardrail.check("Where is my order?") -print(result.is_allowed) # True -``` - -## API Server - -```bash -# Start server -sentinelguard serve --port 8000 - -# Or programmatically -from sentinelguard.api import create_app -app = create_app() -``` - -Endpoints: -- `POST /scan/prompt` - Scan prompt text -- `POST /scan/output` - Scan output text -- `POST /validate` - Validate prompt + output -- `GET /scanners` - List available scanners -- `GET /health` - Health check -- `GET /docs` - Interactive API docs - -## CLI - -```bash -# Scan a prompt -sentinelguard scan prompt "Your text here" - -# Scan with JSON output -sentinelguard scan prompt "Text" --format json - -# Scan with custom config -sentinelguard scan prompt "Text" --config sentinelguard.yaml - -# List scanners -sentinelguard scanners list - -# Create config file -sentinelguard config init --preset strict - -# Start API server -sentinelguard serve --port 8000 -``` - -## Custom Scanners - -```python -from sentinelguard import BaseScanner, ScanResult, RiskLevel, register_scanner - -@register_scanner -class MyCustomScanner(BaseScanner): - scanner_name = "my_scanner" - scanner_type = "both" # "prompt", "output", or "both" - - def scan(self, text, **kwargs): - # Your logic here - is_safe = "bad_word" not in text.lower() - return ScanResult( - is_valid=is_safe, - score=0.0 if is_safe else 1.0, - risk_level=RiskLevel.LOW if is_safe else RiskLevel.HIGH, - details={"custom": "data"}, - ) - -# Use it -guard = SentinelGuard() -guard.use("my_scanner", on="prompt") -``` - -## Async Support - -```python -import asyncio -from sentinelguard import SentinelGuard - -async def main(): - guard = SentinelGuard.minimal() - result = await guard.scan_prompt_async("Hello world") - print(result.is_valid) - -asyncio.run(main()) -``` - -## Examples - -### Python Scripts -- `examples/basic_usage.py` - Core scanning functionality -- `examples/pii_detection.py` - PII detection and anonymization -- `examples/adversarial_detection.py` - Adversarial attack detection -- `examples/embedding_guardrails.py` - Embedding-based topic enforcement - -### Jupyter Notebooks -- `examples/01_basic_usage.ipynb` - Interactive guide to core features -- `examples/02_owasp_security.ipynb` - OWASP LLM Top 10 coverage with examples -- `examples/03_pii_detection.ipynb` - PII detection, anonymization, and data leakage prevention -- `examples/04_adversarial_detection.ipynb` - Adversarial attack detection and defense - -## Comparison - -| Feature | SentinelGuard | LLM-Guard | Guardrails AI | NeMo Guardrails | -|---------|:---:|:---:|:---:|:---:| -| Prompt Scanners | 19 | 15 | Hub | 5 | -| Output Scanners | 17 | 15 | Hub | 5 | -| OWASP LLM Top 10 | Full (10/10) | Partial | - | - | -| PII (Presidio) | 50+ entities | Basic | Via Hub | - | -| Adversarial Detection | Multi-method | - | - | - | -| Embedding Guardrails | Full | - | - | Limited | -| Compliance Checker | Built-in | - | - | - | -| API Server | FastAPI | Yes | Yes | Yes | -| CLI Tool | Yes | Limited | Yes | - | -| Async Support | Full | Partial | Full | Yes | -| Jupyter Notebooks | Yes | - | Yes | - | -| Custom Scanners | Easy | Medium | Hub | Medium | - -## Project Structure - -``` -sentinelguard/ -├── sentinelguard/ -│ ├── core/ # Framework (scanner, config, guard, pipeline) -│ ├── scanners/ -│ │ ├── prompt/ # 19 prompt scanners (OWASP-aligned) -│ │ └── output/ # 17 output scanners (OWASP-aligned) -│ ├── owasp.py # OWASP LLM Top 10 mapping & compliance -│ ├── pii/ # Presidio PII module -│ ├── adversarial/ # Adversarial detection -│ ├── embeddings/ # Embedding guardrails -│ ├── api/ # FastAPI server -│ └── cli/ # CLI tool -├── examples/ # Python scripts + Jupyter notebooks -├── configs/ # Configuration templates -├── tests/ # Test suite (incl. OWASP scanner tests) -└── docs/ # Documentation -``` - ## License MIT License - see [LICENSE](LICENSE) for details. diff --git a/pyproject.toml b/pyproject.toml index 54571eb..e24371d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "sentinelguard" -version = "0.0.4" +version = "0.0.5" description = "A comprehensive, production-ready LLM security and guardrails framework" readme = "README.md" license = {text = "MIT"} diff --git a/sentinelguard/__init__.py b/sentinelguard/__init__.py index c234ab3..4895bd7 100644 --- a/sentinelguard/__init__.py +++ b/sentinelguard/__init__.py @@ -36,7 +36,7 @@ guard = SentinelGuard(config=config) """ -__version__ = "0.0.4" +__version__ = "0.0.5" __author__ = "SentinelGuard Contributors" from sentinelguard.core.guard import SentinelGuard