Metadata-Version: 2.4
Name: sentinel-security
Version: 0.9.0
Summary: Detect and neutralise prompt injection attacks in text and HTML content
Project-URL: Homepage, https://sentinel-agents.com
Project-URL: Documentation, https://github.com/satvoop/Sentinel#readme
Project-URL: Issues, https://github.com/satvoop/Sentinel/issues
Author-email: Sentinel AI <hello@sentinel-agents.com>
License: Proprietary
License-File: LICENSE
Keywords: ai-agents,ai-safety,content-security,langchain,llm-security,middleware,prompt-injection,sanitiser
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Provides-Extra: all
Requires-Dist: cryptography>=41.0.0; extra == 'all'
Requires-Dist: extract-msg>=0.45; extra == 'all'
Requires-Dist: google-api-python-client>=2.0; extra == 'all'
Requires-Dist: google-auth>=2.0; extra == 'all'
Requires-Dist: icalendar>=5.0; extra == 'all'
Requires-Dist: lxml>=4.0; extra == 'all'
Requires-Dist: msal>=1.20; extra == 'all'
Requires-Dist: openpyxl>=3.1; extra == 'all'
Requires-Dist: pillow>=10.0; extra == 'all'
Requires-Dist: pymupdf>=1.23; (python_version >= '3.10') and extra == 'all'
Requires-Dist: python-docx>=1.0; extra == 'all'
Requires-Dist: python-pptx>=0.6; extra == 'all'
Requires-Dist: pyyaml>=6.0; extra == 'all'
Requires-Dist: requests>=2.28; extra == 'all'
Provides-Extra: autogen
Requires-Dist: ag2>=0.4; extra == 'autogen'
Provides-Extra: crewai
Requires-Dist: crewai>=0.80; extra == 'crewai'
Provides-Extra: dev
Requires-Dist: flake8>=6.0; extra == 'dev'
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Provides-Extra: encrypted-rules
Requires-Dist: cryptography>=41.0.0; extra == 'encrypted-rules'
Provides-Extra: frameworks
Requires-Dist: ag2>=0.4; extra == 'frameworks'
Requires-Dist: crewai>=0.80; extra == 'frameworks'
Requires-Dist: haystack-ai>=2.0; extra == 'frameworks'
Requires-Dist: langchain<2.0,>=1.0.0; extra == 'frameworks'
Provides-Extra: google
Requires-Dist: google-api-python-client>=2.0; extra == 'google'
Requires-Dist: google-auth>=2.0; extra == 'google'
Provides-Extra: haystack
Requires-Dist: haystack-ai>=2.0; extra == 'haystack'
Provides-Extra: ics
Requires-Dist: icalendar>=5.0; extra == 'ics'
Provides-Extra: image
Requires-Dist: pillow>=10.0; extra == 'image'
Provides-Extra: langchain
Requires-Dist: langchain<2.0,>=1.0.0; extra == 'langchain'
Provides-Extra: microsoft
Requires-Dist: msal>=1.20; extra == 'microsoft'
Requires-Dist: requests>=2.28; extra == 'microsoft'
Provides-Extra: msg
Requires-Dist: extract-msg>=0.45; extra == 'msg'
Provides-Extra: office
Requires-Dist: lxml>=4.0; extra == 'office'
Requires-Dist: openpyxl>=3.1; extra == 'office'
Requires-Dist: python-docx>=1.0; extra == 'office'
Requires-Dist: python-pptx>=0.6; extra == 'office'
Provides-Extra: pdf
Requires-Dist: pymupdf>=1.23; (python_version >= '3.10') and extra == 'pdf'
Provides-Extra: sheets
Requires-Dist: google-api-python-client>=2.0; extra == 'sheets'
Requires-Dist: google-auth>=2.0; extra == 'sheets'
Provides-Extra: yaml
Requires-Dist: pyyaml>=6.0; extra == 'yaml'
Description-Content-Type: text/markdown

# sentinel-security

Detect and neutralise prompt injection attacks before they reach your AI agent.

sentinel-security scans text and HTML for hidden instructions, invisible characters,
and social engineering patterns that trick LLMs into executing unintended actions.
It returns clean text plus a structured threat report.

## Install

```bash
pip install sentinel-security
```

For Google Sheets scanning:

```bash
pip install sentinel-security[sheets]
```

## Quick start

### Python API

```python
from sentinel_security import sanitise_content

result = sanitise_content(untrusted_text)

if result['risk_level'] != 'CLEAN':
    print(f"Found {result['threat_count']} threats (risk: {result['risk_level']})")
    for threat in result['threats']:
        print(f"  - {threat['type']}: {threat.get('matched', threat.get('detail', ''))}")

clean = result['clean_text']  # safe to pass to your model
```

### HTML content (emails, web pages)

```python
result = sanitise_content(html_email, format='html')
# Strips hidden elements, checks comments, CSS hiding, meta tags
```

### CLI

```bash
# Scan a file
sentinel-scan email.html --format html

# Pipe from stdin
curl -s https://example.com | sentinel-scan --stdin --format html

# CI/CD gate (exit code 0 = clean, 1 = threats found)
sentinel-scan user_input.txt --quiet || echo "BLOCKED"

# Threat report only (no clean text)
sentinel-scan document.txt --threats-only
```

### Google Sheets

```python
from sentinel_security import scan_sheets

result = scan_sheets("spreadsheet_id", credentials=your_google_creds)
# Checks for: hidden sheets, hidden rows/cols, injection in cells,
# text colour matching background, tiny fonts hiding text
```

## What it detects

**Prompt injection patterns**
- "Ignore previous instructions" and 30+ variants
- System prompt overrides (`system: you are`, `[INST]`, `<<SYS>>`)
- Action hijacking ("send email to", "execute this command", "update config")
- Social engineering ("URGENT:", "IMPORTANT:", "authorized maintenance operation")

**Hidden content**
- HTML comments, display:none, visibility:hidden, opacity:0
- Zero-height/width elements, off-screen positioning
- White-on-white text, font-size:0
- Suspicious Open Graph / meta tags

**Unicode attacks**
- 20+ invisible characters (zero-width spaces, joiners, BOM, soft hyphens)
- RTL override attacks (text that renders differently than it reads)
- Homoglyph detection (mixed Latin + Cyrillic in same word)

**Encoding tricks**
- Suspicious base64 blocks (24+ chars, likely encoded instructions)
- Repository metadata injection (HTML comments in markdown, JSON schema $ref)

**Google Sheets specific**
- Hidden sheets, rows, and columns
- Cell text colour matching background (invisible text)
- Extremely small fonts (< 2pt)
- Injection patterns in cell values

## Risk scoring

Every scan returns a risk score (0-10) and risk level:

| Level | Score | Meaning |
|-------|-------|---------|
| CLEAN | 0 | No threats detected |
| LOW | 1-2 | Minor issues (invisible chars) |
| MEDIUM | 3-5 | Suspicious content found |
| HIGH | 6-8 | Likely injection attempt |
| CRITICAL | 9-10 | Active attack detected |

## Output format

```json
{
  "clean_text": "sanitised content with dangerous chars removed",
  "threats": [
    {
      "type": "injection_pattern",
      "matched": "ignore all previous instructions",
      "context": "...surrounding text...",
      "position": 42
    }
  ],
  "threat_count": 1,
  "risk_score": 4,
  "risk_level": "MEDIUM"
}
```

## Use cases

- **AI agent pipelines**: scan web pages, emails, and documents before feeding to your LLM
- **CI/CD gates**: block prompts that contain injection patterns
- **Google Workspace**: scan shared spreadsheets for hidden malicious content
- **Content moderation**: pre-filter user-generated content for injection attempts

## Framework Middleware

Sentinel provides drop-in runtime security for AI agent frameworks. Every LLM call, tool output, and agent response is automatically scanned for prompt injection -- no changes to your agent logic required.

### Install

```bash
# LangChain users
pip install sentinel-security[langchain]

# OpenAI / Anthropic SDK users (no extra deps needed)
pip install sentinel-security
```

### LangChain (AgentMiddleware)

For LangChain v1+ agents using `create_agent()`:

```python
from sentinel_security.middleware import SentinelMiddleware

agent = create_agent(
    model=ChatOpenAI(),
    tools=[...],
    middleware=[SentinelMiddleware()],  # scans inputs + outputs
)
```

### LangChain Legacy / LangGraph (CallbackHandler)

For `create_react_agent`, `BaseChatModel`, or any LangChain component that accepts callbacks:

```python
from sentinel_security.middleware import SentinelCallbackHandler

# With LangGraph create_react_agent:
agent.invoke(
    {"messages": [...]},
    config={"callbacks": [SentinelCallbackHandler()]},
)

# With a raw chat model:
model = ChatOpenAI(callbacks=[SentinelCallbackHandler()])
```

The callback handler scans LLM inputs, outputs, and tool results. It is observation-only -- use `SentinelMiddleware` for blocking support.

### OpenAI SDK

```python
from openai import OpenAI
from sentinel_security.middleware import sentinel_wrap

client = sentinel_wrap(OpenAI())  # one line

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": user_input}],
)
# Streaming is also supported -- responses are buffered and scanned on completion.
```

### Anthropic SDK

```python
from anthropic import Anthropic
from sentinel_security.middleware import sentinel_wrap

client = sentinel_wrap(Anthropic())  # one line

response = client.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=1024,
    messages=[{"role": "user", "content": user_input}],
)
```

Both sync and async clients are supported (`OpenAI`, `AsyncOpenAI`, `Anthropic`, `AsyncAnthropic`). Wrapping is idempotent -- calling `sentinel_wrap()` twice on the same client is safe.

### Global Configuration

Set defaults for all middleware with `configure()`:

```python
import sentinel_security

sentinel_security.configure(
    policy="warn",                     # "log" | "warn" | "block"
    risk_threshold=5,                  # score (0-10) above which policy fires
    event_handler=my_custom_handler,   # optional callback for ScanEvent instances
    licence_key="sk-sent-...",         # optional: activate paid features
)
```

Or use environment variables:

```bash
export SENTINEL_POLICY="warn"
export SENTINEL_RISK_THRESHOLD="5"
export SENTINEL_LICENCE_KEY="sk-sent-..."
```

Precedence (highest first): per-adapter kwargs > `configure()` > environment variables > package defaults.

### Policy Options

| Policy | Behaviour |
|--------|-----------|
| `log`  | Scan and log results. Never block. All content passes through. |
| `warn` | Scan and flag threats at WARNING level. Content passes through. |
| `block` | Scan and raise `SentinelBlockedError` when risk exceeds threshold. |

### Custom Event Handling

Every scan emits a structured `ScanEvent` to Python's `logging` module. You can also receive events programmatically:

```python
from sentinel_security.middleware import ScanEvent

def my_handler(event: ScanEvent):
    if event.action == "block":
        alert_security_team(event.to_dict())

sentinel_security.configure(event_handler=my_handler)
```

### Licence Activation (Python-only)

If you don't use the OpenClaw plugin, activate your licence via environment variable or `configure()`:

```python
sentinel_security.configure(licence_key="sk-sent-...")
# or: export SENTINEL_LICENCE_KEY="sk-sent-..."
```

The key is validated as a SHA-256 hash over HTTPS -- the plaintext key is never sent. Validation results are cached (24h for valid, 5min for invalid). Offline environments get all core features; paid features degrade gracefully.

For the full middleware guide, see [docs/middleware-guide.md](docs/middleware-guide.md) or visit [sentinel-agents.com](https://sentinel-agents.com).

## Requirements

- Python 3.9+
- No dependencies for core text/HTML scanning
- `google-api-python-client` and `google-auth` for Sheets scanning (optional)
- `langchain-core>=0.3.0` for LangChain middleware (optional)
- OpenAI / Anthropic SDK wrapper requires no extra dependencies

## License

Commercial. See [sentinel-agents.com](https://sentinel-agents.com) for licensing.
