|
Download README.md from flowxai/injection: direct link, hf CLI and curl.
- Browser
- Download file 5.31 kB
-
https://huggingface.co/flowxai/injection/resolve/main/README.md
- Command line
-
hf download hf://flowxai/injection/README.md
-
curl -L -o README.md https://huggingface.co/flowxai/injection/resolve/main/README.md
5.31 kB
| license: apache-2.0 | |
| library_name: onnx | |
| pipeline_tag: text-classification | |
| tags: | |
| - prompt-injection | |
| - jailbreak-detection | |
| - guardrails | |
| - onnx | |
| - multilingual | |
| language: [bg, hr, cs, da, nl, en, et, fi, fr, de, el, hu, ga, it, lv, lt, mt, pl, pt, ro, sk, sl, es, sv, tr, az] | |
| base_model: FacebookAI/xlm-roberta-base | |
| # injection | |
| Prompt injection and jailbreak detection over 26 languages. XLM-RoBERTa base, three | |
| independent labels, INT8 ONNX, CPU. Built for | |
| [`flowx-border`](https://github.com/flowx-ai/border), where it is the T2 `injection` | |
| detector. | |
| Labels are multi-label rather than exclusive: `direct_injection`, `indirect_injection`, | |
| `jailbreak`. A single text can be more than one. | |
| ## What changed in this version, and why it is the headline | |
| Three corpora in, the false positives on ordinary customer traffic are gone. Same | |
| architecture and hyperparameters throughout; only the corpus moved. | |
| Measured through the shipped configuration at threshold 0.43: | |
| | | v3 | v4 | **v5, this one** | | |
| |---|---|---|---| | |
| | ordinary support questions it fires on | 7 of 12 | 1 of 12 | **0 of 12** | | |
| | technical identifiers, at 0.43 | 4 of 4 | 0 of 4 | 1 of 4 | | |
| | technical identifiers, at 0.95 | 4 of 4 | 0 of 4 | **0 of 4** | | |
| | the three canonical attacks | 3 of 3 | 3 of 3 | **3 of 3** | | |
| | mean per-language F1 | 0.9755 | 0.9855 | **0.9891** | | |
| | worst language | – | mt 0.8367 | **mt 0.8817** | | |
| v5 added one register, `mundane_account_access`, and it lives in the corpus generator's | |
| shared mundane set so `moderation` and the five single-label classifiers inherit it too. The | |
| gap it fills was invisible because the three registers already there are all prose *about* | |
| things in the third person, a password reset notice or an appointment booking. None of them | |
| was a customer speaking, so "How do I reset my password?" was out of distribution for every | |
| corpus anchored on them, and two detectors independently learned to treat customers as | |
| hostile. | |
| **It is not a clean sweep, and the card should say so.** A bare UUID reads | |
| `direct_injection` at 0.944 under v5, clearing 0.43 where v4 had it at zero. It stays below | |
| 0.95. Net across both shapes v5 is ahead and the regression is real. | |
| The previous model read a bare UUID, a git commit hash, a data URI and a sha256 digest as | |
| `jailbreak` or `direct_injection`, and read *"Someone is using my account, how do I lock | |
| it?"* as `direct_injection` at 0.98. Since the detector ships `on_fail: block`, that made the | |
| default policy refuse most of what a support assistant is asked. Both classes of false | |
| positive came from the same corpus property: every benign register was conversational prose, | |
| so an imperative request and a high-entropy identifier were equally out of distribution. | |
| ## Evaluation | |
| 4,327 held-out rows, threshold 0.43, max_length 96. | |
| | label | precision | recall | F1 | FPR | | |
| |---|---|---|---|---| | |
| | `direct_injection` | 0.9528 | 0.9957 | 0.9738 | 0.0057 | | |
| | `indirect_injection` | 0.9709 | 0.9901 | 0.9804 | 0.0021 | | |
| | `jailbreak` | 0.9367 | 0.9850 | 0.9603 | 0.0077 | | |
| Mean per-language F1 0.9891. Weakest are `mt` 0.8817, then `ga` 0.9762 and `cs` 0.9767. Maltese is not in XLM-RoBERTa's pretraining set, | |
| and that is a fact about the base model rather than a diagnosis: the same gap in another | |
| detector here closed entirely on corpus size alone, so read 0.8367 as a number to improve | |
| and not as a ceiling. | |
| ## Corpus | |
| 45,541 examples: 12,285 attacks and 33,256 benign, 27.0 percent attack share, generated with | |
| `gpt-oss:120b`. 26 languages evenly at 1,656 to 1,690 rows each. 19 registers, including `technical_identifiers` and | |
| `technical_payload`, and four `mundane_*` registers shared with the other classifiers in | |
| this family, of which `mundane_account_access` is v5's addition. | |
| 276 generated rows were rejected before writing: 127 placeholders, 77 duplicates, 50 in the | |
| wrong script for their language, 22 outside their length band. | |
| ## Known weakness | |
| A bare UUID reads `direct_injection` at 0.944, which clears the shipped 0.43 and not 0.95. | |
| v4 had it at zero, so this is a regression on the technical shape bought alongside a fix to | |
| the account-access one. Both are corpus properties rather than thresholds. | |
| The account-access failure v4 could not fix is gone: *"Please cancel my subscription."* read | |
| `direct_injection` at 0.9775 under v4, identical at 0.43 and 0.95 so no threshold reached it. | |
| Two of 35,025 rows matched that phrasing then; v5 has 1,862 rows in the account-access | |
| register and 16 carrying that exact phrasing as benign. | |
| ## Use it at 0.43 | |
| The library ships 0.43, above this run's calibrated 0.02. The calibration deliberately is not | |
| adopted: its own report flags 0.02 as the lowest value in the sweep, which compresses scores | |
| toward zero, and macro F1 is 0.9671 even at 0.95, so the sweep is a plateau rather than a | |
| peak. A missed injection costs more than a review, so the shipped value sits well below the | |
| plateau's top without chasing the floor. | |
| ## Export | |
| INT8 with the Gather-only quantisation recipe. 0 of 300 decisions changed against the fp32 | |
| graph, probability drift p99 0.00005, max 0.15393, and the max is one row where the p99 is what the gate reads. `onnx/export_manifest.json` carries the | |
| weight hashes. | |
| ## Licence | |
| Apache-2.0. Trained on synthetic data generated for this purpose. | |