Metadata-Version: 2.4
Name: tokenbreak-scanner
Version: 0.1.0
Summary: Scanner for TokenBreak vulnerabilities in NLP model artifacts
Author: TokenBreak Scanner Contributors
License: AGPL-3.0-or-later
Project-URL: Homepage, https://github.com/your-org/tokenbreak-scanner
Project-URL: Repository, https://github.com/your-org/tokenbreak-scanner
Project-URL: Documentation, https://github.com/your-org/tokenbreak-scanner#readme
Project-URL: Issues, https://github.com/your-org/tokenbreak-scanner/issues
Keywords: tokenbreak,tokenizer,security,nlp,adversarial,bpe,wordpiece,unigram,huggingface,vulnerability-scanner
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
Classifier: Topic :: Security
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
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: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: transformers>=4.40.0
Requires-Dist: tokenizers>=0.19.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: click>=8.0.0
Requires-Dist: rich>=13.0.0
Requires-Dist: numpy>=1.17
Provides-Extra: attack
Requires-Dist: torch>=2.0.0; extra == "attack"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: httpx>=0.24.0; extra == "dev"
Dynamic: license-file

# 🔐 TokenBreak Scanner — NLP Model Vulnerability Auditor

Detect **TokenBreak adversarial vulnerabilities** in LLMs, classifiers, and encoders before they hit production.

[![PyPI](https://img.shields.io/pypi/v/tokenbreak-scanner)](https://pypi.org/project/tokenbreak-scanner)
[![Python](https://img.shields.io/pypi/pyversions/tokenbreak-scanner)](https://pypi.org/project/tokenbreak-scanner)
[![License](https://img.shields.io/badge/License-AGPL--3.0--or--later-blue.svg)](LICENSE)
[![Tests](https://github.com/your-org/tokenbreak-scanner/actions/workflows/ci.yml/badge.svg)](https://github.com/your-org/tokenbreak-scanner/actions)
[![Downloads](https://img.shields.io/pypi/dm/tokenbreak-scanner)](https://pypi.org/project/tokenbreak-scanner)

[📄 TokenBreak Paper](https://arxiv.org/html/2506.07948v1) · [⚡ Quick Start](#installation) · [📖 Usage](#usage) · [🚀 CI Integration](#ci-integration)

---

## 🔥 What is TokenBreak?

**TokenBreak** is an adversarial attack that bypasses text-classification and LLM guardrails by prepending a single character to targeted words. This tiny perturbation corrupts **BPE** and **WordPiece** tokenization, causing models to misclassify malicious input as benign — while humans and downstream LLMs still understand the original meaning.

> 📄 **Paper**: [TokenBreak: Bypassing Text Classification Models Through Token Manipulation](https://arxiv.org/html/2506.07948v1)

---

## 🛡️ What TokenBreak Scanner Does

| Capability | Description |
|---|---|
| **Inspect model artifacts** | Reads `config.json`, `tokenizer.json`, `tokenizer_config.json` to determine tokenizer architecture |
| **Identify tokenization algorithm** | Detects **BPE**, **WordPiece**, **Unigram**, or **SentencePiece** |
| **Assess TokenBreak vulnerability** | Flags BPE/WordPiece models as **High Risk**; Unigram as **Safe** |
| **Explain the decision** | Evidence tree showing which signals (config, runtime, source) contributed to the confidence score |
| **Recommend defense** | Suggests the Unigram pre-mapping defense (Section 5) or migration to a safer model family |
| **Live attack validation** *(optional)* | Loads model weights and runs the `BreakPrompt` algorithm to verify the bypass experimentally |

---

## 📦 Installation

### From PyPI (recommended)

```bash
pip install tokenbreak-scanner
```

### Optional extras

- **Attack validation** (requires PyTorch):
  ```bash
  pip install "tokenbreak-scanner[attack]"
  ```
- **Development dependencies** (pytest, coverage):
  ```bash
  pip install "tokenbreak-scanner[dev]"
  ```

### From source

```bash
git clone https://github.com/your-org/tokenbreak-scanner.git
cd tokenbreak-scanner
pip install -e ".[dev]"
```

---

## 🚀 Quick Start

### Scan a local model directory

```bash
tokenbreak-scan ./models/my-spam-classifier/
```

### Scan a HuggingFace model ID (auto-download)

```bash
tokenbreak-scan distilbert-base-uncased --download
```

### Scan Qwen3-0.6B (production example)

```bash
tokenbreak-scan Qwen/Qwen3-0.6B --download --trust-remote-code
```

> ✅ Expected result: **HIGH risk** — Qwen uses BPE tokenization and is vulnerable to TokenBreak.

### JSON output (for CI pipelines)

```bash
tokenbreak-scan <model> --output json
```

### Run live attack validation

```bash
tokenbreak-scan <model> --test-attack
```

---

## 🧪 Example Output

### Table format (vulnerable model)

```
======================================================================
               TOKENBREAK SCANNER REPORT
======================================================================
  Model Name:       distilbert-base-uncased
  Model Type:       distilbert
  Family:           DistilBERT
  Tokenizer Class:  DistilBertTokenizerFast
  Algorithm:        WordPiece
  Vocab Size:       30522
  Confidence:       0.85
  Vulnerable:       YES ⚠️
  Risk Level:       High
======================================================================
  Detection Sources:
    1. [tokenizer.json model.type] weight=0.40 -> WordPiece
    2. [tokenizer_config.json class] weight=0.20 -> WordPiece
    3. [config.json model_type] weight=0.15 -> WordPiece
======================================================================
  Recommendation:
    Model is vulnerable to TokenBreak. Recommended: Implement the
    Unigram pre-mapping defense by inserting a Unigram tokenizer
    before classification and remapping tokens, or migrate to a
    model family using Unigram tokenization.
======================================================================
```

### JSON format

```json
{
  "model_name": "distilbert-base-uncased",
  "model_type": "distilbert",
  "model_family": "DistilBERT",
  "tokenizer_class": "DistilBertTokenizerFast",
  "tokenizer_algorithm": "WordPiece",
  "vocab_size": 30522,
  "confidence_score": 0.85,
  "vulnerable_to_tokenbreak": true,
  "risk_level": "High",
  "detection_sources": [...],
  "recommendation": "...",
  "source": "/path/to/model"
}
```

---

## 🔄 CI Integration

Use exit codes to gate vulnerable models in your MLOps pipeline:

| Exit code | Meaning |
|---|---|
| `0` | Model is **safe** (Unigram) or unknown |
| `1` | Model is **vulnerable** (BPE or WordPiece) — block deployment |
| `2` | Error (path not found, download failed, etc.) |

### GitHub Actions example

```yaml
- name: Scan model for TokenBreak vulnerability
  run: |
    pip install tokenbreak-scanner
    tokenbreak-scan ./models-to-deploy/ --output json > scan-report.json
    cat scan-report.json
```

### Python SDK example

```python
from tokenbreak_scanner.inspector import inspect_model
from tokenbreak_scanner.models import RiskLevel

report = inspect_model(model_path, download=False)
if report.risk_level == RiskLevel.HIGH:
    raise RuntimeError(f"Deployment blocked: {report.model_name} is vulnerable to TokenBreak")
```

---

## 🔬 How the Attack Works

1. **Attack vector**: Prepend a single character (A–Z or a–z) to high-impact words, forcing BPE/WordPiece to split tokens differently.
2. **Effect**: The protection model misclassifies the input (false negative), while the downstream LLM or human reviewer still understands it.
3. **Defense**: Insert a Unigram tokenizer before the target tokenizer. Unigram tokenizes based on probability rather than left-to-right merges, making it naturally resistant to character-level perturbations.

---

## 📊 Supported Model Families

| Family | Algorithm | TokenBreak Risk |
|---|---|---|
| GPT-2, GPT-J, GPT-Neo, GPT-NeoX | BPE | 🔴 **HIGH** |
| LLaMA, Mistral, Mixtral, Falcon | BPE | 🔴 **HIGH** |
| Qwen, Qwen2, Qwen3 | BPE | 🔴 **HIGH** |
| Gemma, Gemma 2 | BPE | 🔴 **HIGH** |
| Phi-3, Phi-4 | BPE | 🔴 **HIGH** |
| BLOOM, BigScience | BPE | 🔴 **HIGH** |
| Cohere, Command R | BPE | 🔴 **HIGH** |
| BERT, DistilBERT, RoBERTa | WordPiece / BPE | 🔴 **HIGH** |
| DeBERTa-v2, DeBERTa-v3 | Unigram | 🟢 **LOW** |
| XLM-RoBERTa | Unigram | 🟢 **LOW** |
| ALBERT | Unigram | 🟢 **LOW** |
| mT5, T5 (SentencePiece Unigram) | Unigram | 🟢 **LOW** |

> 📋 Full mapping in `src/tokenbreak_scanner/tokenizers.py`

---

## 🏗️ Architecture

```
tokenbreak_scanner/
├── __init__.py      # Package version
├── cli.py           # Click CLI with Rich table / JSON output
├── inspector.py     # Core introspection engine (6-signal weighted aggregation)
├── models.py        # Pydantic schemas: ScannerReport, DetectionSource, RiskLevel
├── tokenizers.py    # Tokenizer type detection, model-family mapping, runtime inspection
└── validator.py     # Optional live attack validation via BreakPrompt
```

### Detection signals (weighted evidence tree)

| Signal | Weight | Source |
|---|---|---|
| `tokenizer.json` model type | 0.40 | HuggingFace tokenizer artifact |
| Runtime `_tokenizer.model` | 0.40 | Live Rust backend inspection |
| Source-code fingerprint | 0.30 | Python module keyword matching |
| Remote source file | 0.30 | HF Hub downloaded tokenizer module |
| `tokenizer_config.json` class | 0.20 | Config metadata |
| `config.json` model_type | 0.15 | Architecture fallback |

---

## 🧪 Testing

```bash
pytest tests/ -v
```

All 33+ tests cover:
- Local model directory scanning (BPE, WordPiece, Unigram)
- Missing `tokenizer.json` fallback
- CLI table and JSON output modes
- Tokenizer class name → algorithm mapping

---

## 🤝 Contributing

Contributions are welcome! Please open an issue or pull request.

1. Fork the repository
2. Create a feature branch (`git checkout -b feat/amazing-feature`)
3. Commit your changes (`git commit -m 'feat: add amazing feature'`)
4. Push to the branch (`git push origin feat/amazing-feature`)
5. Open a Pull Request

---

## 📜 License

This project is licensed under the **GNU Affero General Public License v3.0 or later (AGPL-3.0+)**.

- ✅ Freedom to use, modify, and distribute
- 🔒 Copyleft: derivative works and services must also be open-sourced under AGPL
- 🌐 Network use counts as distribution — remote users are entitled to the source code

See [LICENSE](LICENSE) for the full text: <https://www.gnu.org/licenses/agpl-3.0.html>

---

## 🔗 Related

- 📄 [TokenBreak Paper (arXiv 2506.07948v1)](https://arxiv.org/html/2506.07948v1)
- 🦾 [HuggingFace Transformers](https://github.com/huggingface/transformers)
- 🔬 [Adversarial Robustness Toolbox](https://github.com/Trusted-AI/adversarial-robustness-toolbox)
- 🛡️ [OWASP Machine Learning Security Top 10](https://owasp.org/www-project-machine-learning-security-top-10/)
- 🧠 [AI Village](https://aivillage.org/)
