Metadata-Version: 2.4
Name: jinja2-ssti-sanitizer
Version: 0.1.0
Summary: Detect and neutralize Jinja2 server-side template injection (SSTI) payloads
Project-URL: Homepage, https://github.com/kjsxz/sanitizer-library
Project-URL: Documentation, https://github.com/kjsxz/sanitizer-library#readme
Project-URL: Repository, https://github.com/kjsxz/sanitizer-library
Project-URL: Issues, https://github.com/kjsxz/sanitizer-library/issues
Author: Aisle Security
License-Expression: MIT
License-File: LICENSE
Keywords: jinja2,sanitizer,security,server-side-template-injection,ssti,template-injection
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
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
Classifier: Typing :: Typed
Requires-Python: >=3.9
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: jinja2>=3.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: twine>=4.0; extra == 'dev'
Provides-Extra: render
Requires-Dist: jinja2>=3.0; extra == 'render'
Description-Content-Type: text/markdown

# jinja2-ssti-sanitizer

Detect and neutralize **Jinja2 server-side template injection (SSTI)** payloads before they reach your templates.

[![CI](https://github.com/kjsxz/sanitizer-library/actions/workflows/ci.yml/badge.svg)](https://github.com/kjsxz/sanitizer-library/actions/workflows/ci.yml)
[![PyPI version](https://img.shields.io/pypi/v/jinja2-ssti-sanitizer)](https://pypi.org/project/jinja2-ssti-sanitizer/)

## Installation

```bash
pip install jinja2-ssti-sanitizer
```

For safe rendering helpers that use Jinja2's `SandboxedEnvironment`:

```bash
pip install jinja2-ssti-sanitizer[render]
```

## Quick start

```python
from jinja2_ssti_sanitizer import (
    is_jinja2_payload,
    sanitize_jinja2_input,
    render_safely,
)

# Detect SSTI attempts in user input
if is_jinja2_payload(user_input):
    raise ValueError("blocked")

# Escape delimiters and strip gadget fragments
result = sanitize_jinja2_input(user_input)
safe_text = result.sanitized

# Render a fixed template with a validated context
html = render_safely("Hello {{ name }}!", {"name": user_name})
```

## API

| Function | Description |
| --- | --- |
| `detect_threats(value)` | Returns threat level and matched rule names |
| `is_jinja2_payload(value)` | `True` when input matches SSTI patterns |
| `sanitize_jinja2_input(value, mode="escape")` | Neutralize input (`escape`, `strip`, or `reject`) |
| `validate_template_variable(name, value)` | Validate a single context value |
| `validate_template_context(context)` | Validate all string values in a render context |
| `create_safe_environment()` | `SandboxedEnvironment` with safe defaults |
| `render_safely(template_source, context)` | Render with validated context |

### Sanitization modes

- **`escape`** (default) — HTML-entity-encode `{{`, `}}`, `{%`, `%}`, `{#`, `#}` and strip gadget fragments
- **`strip`** — remove delimiter tokens and dangerous expressions
- **`reject`** — raise `ValueError` on HIGH or CRITICAL threats

Critical payloads (dunder chains, `mro`, `subclasses`, `import`/`include` tags, etc.) are always rejected when `reject_critical=True` (the default).

## What it protects against

- Jinja2 variable, block, and comment delimiters
- Common gadget chains (`__class__`, `mro`, `subclasses`, `config`, `request`, `attr` filter, …)
- Unicode homoglyphs and zero-width bypass characters

## Defense in depth

This library is a **input-validation layer**, not a substitute for secure design:

1. **Never** build template source from user-controlled input.
2. Use `SandboxedEnvironment` with autoescape enabled.
3. Sanitize or reject untrusted strings before they enter template context.

## Development

```bash
git clone https://github.com/kjsxz/sanitizer-library.git
cd sanitizer-library
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest
python -m build
```

## Publishing to PyPI

Releases are published automatically when a GitHub Release is created.

### One-time setup

1. Create a PyPI project at [pypi.org](https://pypi.org/) (or [test.pypi.org](https://test.pypi.org/) first).
2. Configure [trusted publishing](https://docs.pypi.org/trusted-publishers/) on PyPI:
   - **Publisher**: GitHub Actions
   - **Repository**: `kjsxz/sanitizer-library`
   - **Workflow**: `publish.yml`
   - **Environment**: `pypi`
3. In GitHub repo settings, create an environment named `pypi` (optional approval gate).

### Release flow

```bash
# Bump version in pyproject.toml and jinja2_ssti_sanitizer/__init__.py
git tag v0.1.0
git push origin v0.1.0
```

Then create a GitHub Release from the tag. The publish workflow uploads to PyPI.

Manual publish (maintainers):

```bash
pip install build twine
python -m build
twine upload dist/*
```

## License

MIT — see [LICENSE](LICENSE).
