resksecure 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- resksecure-0.1.0/.github/workflows/publish.yml +51 -0
- resksecure-0.1.0/.github/workflows/tests.yml +38 -0
- resksecure-0.1.0/.gitignore +10 -0
- resksecure-0.1.0/LICENSE +105 -0
- resksecure-0.1.0/PKG-INFO +238 -0
- resksecure-0.1.0/README.md +206 -0
- resksecure-0.1.0/examples/integration.py +79 -0
- resksecure-0.1.0/pyproject.toml +57 -0
- resksecure-0.1.0/src/resksecure/__init__.py +57 -0
- resksecure-0.1.0/src/resksecure/bitmask_processor.py +152 -0
- resksecure-0.1.0/src/resksecure/cache.py +53 -0
- resksecure-0.1.0/src/resksecure/config/example_policy.yaml +98 -0
- resksecure-0.1.0/src/resksecure/policy_loader.py +95 -0
- resksecure-0.1.0/src/resksecure/policy_watcher.py +72 -0
- resksecure-0.1.0/src/resksecure/tool_guard.py +40 -0
- resksecure-0.1.0/src/resksecure/trie_factory.py +130 -0
- resksecure-0.1.0/tests/__init__.py +0 -0
- resksecure-0.1.0/tests/test_bitmask_processor.py +147 -0
- resksecure-0.1.0/tests/test_cache.py +52 -0
- resksecure-0.1.0/tests/test_policy_loader.py +85 -0
- resksecure-0.1.0/tests/test_tool_guard.py +61 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
publish_to_pypi:
|
|
9
|
+
description: "Publish to PyPI (true) or TestPyPI (false)"
|
|
10
|
+
required: true
|
|
11
|
+
default: "true"
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
build-and-publish:
|
|
15
|
+
name: Build and publish Python package
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
permissions:
|
|
18
|
+
id-token: write
|
|
19
|
+
contents: read
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout repository
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- name: Set up Python
|
|
26
|
+
uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: "3.13"
|
|
29
|
+
|
|
30
|
+
- name: Install build tools
|
|
31
|
+
run: |
|
|
32
|
+
python -m pip install --upgrade pip
|
|
33
|
+
pip install hatchling
|
|
34
|
+
|
|
35
|
+
- name: Build package
|
|
36
|
+
run: python -m hatchling build
|
|
37
|
+
|
|
38
|
+
- name: Publish to PyPI
|
|
39
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
40
|
+
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.publish_to_pypi == 'true') }}
|
|
41
|
+
with:
|
|
42
|
+
packages-dir: dist/
|
|
43
|
+
password: ${{ secrets.PYPI_TOKEN }}
|
|
44
|
+
|
|
45
|
+
- name: Publish to TestPyPI
|
|
46
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
47
|
+
if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_to_pypi != 'true' }}
|
|
48
|
+
with:
|
|
49
|
+
repository-url: https://test.pypi.org/legacy/
|
|
50
|
+
packages-dir: dist/
|
|
51
|
+
password: ${{ secrets.PYPI_TOKEN }}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Run tests
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.13", "3.14"]
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout repository
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
22
|
+
uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: |
|
|
28
|
+
python -m pip install --upgrade pip
|
|
29
|
+
pip install -e .[dev]
|
|
30
|
+
|
|
31
|
+
- name: Lint with ruff
|
|
32
|
+
run: ruff check src/ tests/
|
|
33
|
+
|
|
34
|
+
- name: Run tests
|
|
35
|
+
run: python -m pytest tests/ -v
|
|
36
|
+
|
|
37
|
+
- name: Test import
|
|
38
|
+
run: python -c "from resksecure import BitmaskLogitsProcessor, load_policy, verify_tool_action; print('All imports OK')"
|
resksecure-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
RESK SOFTWARE LICENSE
|
|
2
|
+
Version 1.0, June 2026
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 RESK Security
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS
|
|
7
|
+
|
|
8
|
+
1. Definitions
|
|
9
|
+
|
|
10
|
+
"Software" means the source code, documentation, and any accompanying
|
|
11
|
+
materials in this repository.
|
|
12
|
+
|
|
13
|
+
"Licensor" means RESK Security.
|
|
14
|
+
|
|
15
|
+
"Licensee" means any individual or entity that accesses or uses the Software.
|
|
16
|
+
|
|
17
|
+
"Commercial Use" means any use of the Software where the primary purpose
|
|
18
|
+
is commercial advantage or monetary compensation, including but not limited
|
|
19
|
+
to: integrating the Software into a commercial product, offering the Software
|
|
20
|
+
as part of a SaaS service, using the Software for internal business operations
|
|
21
|
+
that generate revenue, or distributing the Software in exchange for any form
|
|
22
|
+
of payment.
|
|
23
|
+
|
|
24
|
+
"Royalty" means the recurring fee payable to Licensor for any Commercial Use
|
|
25
|
+
of the Software, as defined in a separate commercial agreement.
|
|
26
|
+
|
|
27
|
+
2. Grant of License
|
|
28
|
+
|
|
29
|
+
Subject to the terms and conditions of this License, Licensor grants Licensee
|
|
30
|
+
a non-exclusive, non-transferable, non-sublicensable, limited license to:
|
|
31
|
+
|
|
32
|
+
(a) View and study the Software source code.
|
|
33
|
+
(b) Use the Software for non-commercial, personal, educational, or
|
|
34
|
+
evaluation purposes only.
|
|
35
|
+
(c) Modify the Software for personal, non-commercial use only.
|
|
36
|
+
|
|
37
|
+
3. Prohibited Uses
|
|
38
|
+
|
|
39
|
+
Without the prior written consent of Licensor, Licensee may NOT:
|
|
40
|
+
|
|
41
|
+
(a) Use the Software for any Commercial Use.
|
|
42
|
+
(b) Distribute, sublicense, sell, lease, rent, or transfer the Software
|
|
43
|
+
or any derivative thereof to any third party.
|
|
44
|
+
(c) Incorporate the Software or any portion thereof into any product or
|
|
45
|
+
service offered to third parties.
|
|
46
|
+
(d) Remove or alter any copyright, trademark, or proprietary notice
|
|
47
|
+
contained in the Software.
|
|
48
|
+
(e) Use the Software in any manner that competes with Licensor's business.
|
|
49
|
+
(f) Create derivative works based on the Software for distribution or
|
|
50
|
+
Commercial Use.
|
|
51
|
+
(g) Use the Software in any environment that processes sensitive personal
|
|
52
|
+
data without prior written authorization from Licensor.
|
|
53
|
+
|
|
54
|
+
4. Commercial License and Royalties
|
|
55
|
+
|
|
56
|
+
Any Commercial Use of the Software requires a separate commercial license
|
|
57
|
+
agreement signed by both parties. Such agreement shall specify:
|
|
58
|
+
|
|
59
|
+
(a) The scope of permitted Commercial Use.
|
|
60
|
+
(b) Royalty fees, which shall be calculated as a percentage of revenue or
|
|
61
|
+
a fixed fee per deployment, as agreed upon in writing.
|
|
62
|
+
(c) Duration and renewal terms.
|
|
63
|
+
|
|
64
|
+
Contact: resk-security@proton.me for commercial licensing inquiries.
|
|
65
|
+
|
|
66
|
+
5. Intellectual Property
|
|
67
|
+
|
|
68
|
+
All right, title, and interest in and to the Software, including all
|
|
69
|
+
intellectual property rights therein, remain the exclusive property of
|
|
70
|
+
Licensor. This License does not transfer any ownership rights to Licensee.
|
|
71
|
+
|
|
72
|
+
6. No Warranty
|
|
73
|
+
|
|
74
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
75
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
76
|
+
FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
77
|
+
THE LICENSOR BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
|
|
78
|
+
IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN
|
|
79
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
80
|
+
|
|
81
|
+
7. Limitation of Liability
|
|
82
|
+
|
|
83
|
+
In no event shall Licensor be liable for any indirect, incidental, special,
|
|
84
|
+
consequential, or punitive damages, including but not limited to loss of
|
|
85
|
+
profits, data, or use, arising out of or in connection with the Software,
|
|
86
|
+
whether based on warranty, contract, tort, or any other legal theory, even
|
|
87
|
+
if Licensor has been advised of the possibility of such damages.
|
|
88
|
+
|
|
89
|
+
8. Termination
|
|
90
|
+
|
|
91
|
+
This License terminates automatically if Licensee fails to comply with any
|
|
92
|
+
of its terms. Upon termination, Licensee must immediately cease all use of
|
|
93
|
+
the Software and destroy all copies. Licensor reserves the right to pursue
|
|
94
|
+
legal remedies for any unauthorized use.
|
|
95
|
+
|
|
96
|
+
9. Governing Law
|
|
97
|
+
|
|
98
|
+
This License shall be governed by and construed in accordance with the laws
|
|
99
|
+
of France, without regard to its conflict of laws principles.
|
|
100
|
+
|
|
101
|
+
10. Entire Agreement
|
|
102
|
+
|
|
103
|
+
This License constitutes the entire agreement between the parties concerning
|
|
104
|
+
the subject matter hereof and supersedes all prior agreements and
|
|
105
|
+
understandings.
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: resksecure
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Bitmask-based LLM security firewall with policy-driven logits filtering using GPU-accelerated Aho-Corasick pattern matching
|
|
5
|
+
Project-URL: Homepage, https://github.com/Resk-Security/reskSecure
|
|
6
|
+
Project-URL: Repository, https://github.com/Resk-Security/reskSecure
|
|
7
|
+
Project-URL: Documentation, https://github.com/Resk-Security/reskSecure
|
|
8
|
+
Author: RESK Security
|
|
9
|
+
License: RESK Software License
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: aho-corasick,bitmask,dlp,filtering,firewall,gpu,llm,logits,permissions,policy,safety,security,transformers
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: Other/Proprietary License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
+
Classifier: Topic :: Security
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Requires-Python: >=3.13
|
|
22
|
+
Requires-Dist: pyyaml>=6.0
|
|
23
|
+
Requires-Dist: resklogits>=0.1.0
|
|
24
|
+
Requires-Dist: torch>=2.0.0
|
|
25
|
+
Requires-Dist: transformers>=4.35.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: black>=23.0.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# reskSecure
|
|
34
|
+
|
|
35
|
+
[](https://pypi.org/project/resksecure/)
|
|
36
|
+
[](https://pypi.org/project/resksecure/)
|
|
37
|
+
[](https://pypi.org/project/resksecure/)
|
|
38
|
+
[](LICENSE)
|
|
39
|
+
|
|
40
|
+
**Bitmask-based LLM security firewall.** A Python package that restricts what a language model can generate based on user permissions encoded as a bitmask. It works by intercepting the model's token predictions and blocking or penalizing disallowed phrases before they appear in the output.
|
|
41
|
+
|
|
42
|
+
Available on [PyPI](https://pypi.org/project/resksecure/).
|
|
43
|
+
|
|
44
|
+
Unlike prompt-based filters (which can be jailbroken) or post-generation content moderation (which lets forbidden content leak before detection), reskSecure acts at the logits level -- directly inside the model's generation loop. Each token must pass through the security policy before being emitted.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## How it works
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
User request with bitmask (e.g. 7)
|
|
52
|
+
|
|
|
53
|
+
v
|
|
54
|
+
BitmaskLogitsProcessor intercepts each token prediction
|
|
55
|
+
|
|
|
56
|
+
v
|
|
57
|
+
For every candidate token, the Aho-Corasick automaton (from resklogits)
|
|
58
|
+
checks if selecting it would start or complete a banned phrase
|
|
59
|
+
|
|
|
60
|
+
v
|
|
61
|
+
Hard-mode phrases: the token's logit is set to -inf (impossible to generate)
|
|
62
|
+
Bias-mode phrases: the token's logit is reduced by a configurable penalty
|
|
63
|
+
|
|
|
64
|
+
v
|
|
65
|
+
On complete match: EOS token is forced, generation stops immediately
|
|
66
|
+
|
|
|
67
|
+
v
|
|
68
|
+
Output response or tool call
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Tool calls are also blocked at the token level. If the user's bitmask does not
|
|
72
|
+
contain the required bit for a tool, that tool's trigger phrases (like
|
|
73
|
+
`"send_email("` or `"create_ticket("`) are automatically added to the
|
|
74
|
+
hard-mode blocked list. The model can never generate the first token of
|
|
75
|
+
a disallowed tool call, regardless of prompt engineering or jailbreak
|
|
76
|
+
attempts.
|
|
77
|
+
|
|
78
|
+
A post-generation check (`verify_tool_action`) is also available as a
|
|
79
|
+
defense-in-depth layer, but the primary protection is at the logits level.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Why not just prompt engineering?
|
|
84
|
+
|
|
85
|
+
- Prompt injections can bypass instruction-based filters
|
|
86
|
+
- Post-generation regex or classifier scans catch violations after they appear, but the forbidden content has already been emitted
|
|
87
|
+
- Logits-level filtering blocks tokens before they are sampled -- the model never "sees" the banned sequence as a completion candidate
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Features
|
|
92
|
+
|
|
93
|
+
- **Two severity modes**: `hard` blocks tokens completely (-inf logit), `bias` reduces probability by a configurable penalty
|
|
94
|
+
- **Strict mode**: forces end-of-sequence as soon as the generated prefix matches the start of a banned phrase, even before the full phrase is formed
|
|
95
|
+
- **GPU-accelerated pattern matching**: uses VectorizedAhoCorasick from the resklogits package for fast token scanning
|
|
96
|
+
- **Policy system**: YAML configuration associates capability bitmasks with phrase rules and tool permissions
|
|
97
|
+
- **Hot-reload**: PolicyWatcher detects file changes and rebuilds the automaton without restarting the server
|
|
98
|
+
- **Thread-safe cache**: automata are cached by (mask, model_name) with configurable TTL
|
|
99
|
+
- **Tool guard**: post-generation bitmask check for tool call execution
|
|
100
|
+
- **No JWT handling**: the package receives a raw integer bitmask; authentication and JWT decoding are handled by the calling application
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Requirements
|
|
105
|
+
|
|
106
|
+
- Python >= 3.13
|
|
107
|
+
- PyTorch >= 2.0.0
|
|
108
|
+
- transformers >= 4.35.0
|
|
109
|
+
- resklogits >= 0.1.0
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Installation
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
pip install resksecure
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
[](https://pypi.org/project/resksecure/)
|
|
120
|
+
[](https://pypi.org/project/resksecure/)
|
|
121
|
+
|
|
122
|
+
From source:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
git clone https://github.com/Resk-Security/reskSecure.git
|
|
126
|
+
cd reskSecure
|
|
127
|
+
pip install -e .
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Quick start
|
|
133
|
+
|
|
134
|
+
Define a policy file (`policy.yaml`):
|
|
135
|
+
|
|
136
|
+
```yaml
|
|
137
|
+
version: "1.0"
|
|
138
|
+
policies:
|
|
139
|
+
- mask: 7
|
|
140
|
+
name: contributor
|
|
141
|
+
strict: false
|
|
142
|
+
default: true
|
|
143
|
+
rules:
|
|
144
|
+
- phrase: "DROP TABLE"
|
|
145
|
+
mode: hard
|
|
146
|
+
- phrase: "DELETE FROM"
|
|
147
|
+
mode: hard
|
|
148
|
+
- phrase: "salaries"
|
|
149
|
+
mode: bias
|
|
150
|
+
penalty: -5.0
|
|
151
|
+
tools:
|
|
152
|
+
read_email:
|
|
153
|
+
required_bit: 0
|
|
154
|
+
send_email:
|
|
155
|
+
required_bit: 1
|
|
156
|
+
read_sql:
|
|
157
|
+
required_bit: 2
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Use it in your generation pipeline:
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
from resksecure import BitmaskLogitsProcessor, load_policy, verify_tool_action
|
|
164
|
+
|
|
165
|
+
policy_set = load_policy("policy.yaml")
|
|
166
|
+
|
|
167
|
+
processor = BitmaskLogitsProcessor(
|
|
168
|
+
mask=7,
|
|
169
|
+
model_name="mistralai/Mistral-7B-v0.1",
|
|
170
|
+
tokenizer=tokenizer,
|
|
171
|
+
policy_set=policy_set,
|
|
172
|
+
device="cuda",
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
outputs = model.generate(**inputs, logits_processor=[processor])
|
|
176
|
+
|
|
177
|
+
# Optional: verify tool calls against the bitmask
|
|
178
|
+
if has_tool_call(response):
|
|
179
|
+
if not verify_tool_action("send_email", user_mask=7, policy_set=policy_set):
|
|
180
|
+
raise PermissionError("Action not authorized")
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Policy reference
|
|
186
|
+
|
|
187
|
+
Policy-level fields:
|
|
188
|
+
|
|
189
|
+
| Field | Type | Description |
|
|
190
|
+
|-------------|---------|----------------------------------------------------------|
|
|
191
|
+
| `mask` | int | Capability bitmask that identifies this policy |
|
|
192
|
+
| `name` | string | Human-readable policy name |
|
|
193
|
+
| `strict` | bool | If true, stop generation at the first banned prefix |
|
|
194
|
+
| `default` | bool | If true, this policy is used when no exact mask matches |
|
|
195
|
+
| `rules` | list | List of phrase rules (see below) |
|
|
196
|
+
| `tools` | dict | Map of tool names to tool rule objects (see below) |
|
|
197
|
+
|
|
198
|
+
Phrase rule fields:
|
|
199
|
+
|
|
200
|
+
| Field | Type | Description |
|
|
201
|
+
|-----------|--------|------------------------------------------------------------|
|
|
202
|
+
| `phrase` | string | Text pattern to ban or penalize |
|
|
203
|
+
| `mode` | string | Either `hard` (block completely) or `bias` (reduce logits) |
|
|
204
|
+
| `penalty` | float | Logit penalty for bias mode (e.g. -5.0) |
|
|
205
|
+
|
|
206
|
+
Tool rule fields:
|
|
207
|
+
|
|
208
|
+
| Field | Type | Description |
|
|
209
|
+
|--------------------|----------|----------------------------------------------------------------|
|
|
210
|
+
| `required_bit` | int | Bit position that must be set in the user mask to use this tool |
|
|
211
|
+
| `trigger_phrases` | string[] | Phrases that start this tool call (blocked if bit not set) |
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Package structure
|
|
216
|
+
|
|
217
|
+
```
|
|
218
|
+
reskSecure/
|
|
219
|
+
src/resksecure/
|
|
220
|
+
__init__.py Public exports, version
|
|
221
|
+
policy_loader.py YAML parsing, Policy/PolicySet models
|
|
222
|
+
trie_factory.py Builds VectorizedAhoCorasick from a Policy
|
|
223
|
+
bitmask_processor.py BitmaskLogitsProcessor (LogitsProcessor subclass)
|
|
224
|
+
tool_guard.py Post-generation tool action verification
|
|
225
|
+
cache.py Thread-safe TTL cache for automata
|
|
226
|
+
policy_watcher.py Hot-reload daemon that watches YAML mtime
|
|
227
|
+
config/example_policy.yaml
|
|
228
|
+
tests/
|
|
229
|
+
examples/
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## License
|
|
235
|
+
|
|
236
|
+
This software is licensed under the RESK Software License. Commercial use requires a separate paid license. See the [LICENSE](LICENSE) file for details.
|
|
237
|
+
|
|
238
|
+
For commercial licensing inquiries, contact: contact@resk.fr
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# reskSecure
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/resksecure/)
|
|
4
|
+
[](https://pypi.org/project/resksecure/)
|
|
5
|
+
[](https://pypi.org/project/resksecure/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
**Bitmask-based LLM security firewall.** A Python package that restricts what a language model can generate based on user permissions encoded as a bitmask. It works by intercepting the model's token predictions and blocking or penalizing disallowed phrases before they appear in the output.
|
|
9
|
+
|
|
10
|
+
Available on [PyPI](https://pypi.org/project/resksecure/).
|
|
11
|
+
|
|
12
|
+
Unlike prompt-based filters (which can be jailbroken) or post-generation content moderation (which lets forbidden content leak before detection), reskSecure acts at the logits level -- directly inside the model's generation loop. Each token must pass through the security policy before being emitted.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## How it works
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
User request with bitmask (e.g. 7)
|
|
20
|
+
|
|
|
21
|
+
v
|
|
22
|
+
BitmaskLogitsProcessor intercepts each token prediction
|
|
23
|
+
|
|
|
24
|
+
v
|
|
25
|
+
For every candidate token, the Aho-Corasick automaton (from resklogits)
|
|
26
|
+
checks if selecting it would start or complete a banned phrase
|
|
27
|
+
|
|
|
28
|
+
v
|
|
29
|
+
Hard-mode phrases: the token's logit is set to -inf (impossible to generate)
|
|
30
|
+
Bias-mode phrases: the token's logit is reduced by a configurable penalty
|
|
31
|
+
|
|
|
32
|
+
v
|
|
33
|
+
On complete match: EOS token is forced, generation stops immediately
|
|
34
|
+
|
|
|
35
|
+
v
|
|
36
|
+
Output response or tool call
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Tool calls are also blocked at the token level. If the user's bitmask does not
|
|
40
|
+
contain the required bit for a tool, that tool's trigger phrases (like
|
|
41
|
+
`"send_email("` or `"create_ticket("`) are automatically added to the
|
|
42
|
+
hard-mode blocked list. The model can never generate the first token of
|
|
43
|
+
a disallowed tool call, regardless of prompt engineering or jailbreak
|
|
44
|
+
attempts.
|
|
45
|
+
|
|
46
|
+
A post-generation check (`verify_tool_action`) is also available as a
|
|
47
|
+
defense-in-depth layer, but the primary protection is at the logits level.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Why not just prompt engineering?
|
|
52
|
+
|
|
53
|
+
- Prompt injections can bypass instruction-based filters
|
|
54
|
+
- Post-generation regex or classifier scans catch violations after they appear, but the forbidden content has already been emitted
|
|
55
|
+
- Logits-level filtering blocks tokens before they are sampled -- the model never "sees" the banned sequence as a completion candidate
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Features
|
|
60
|
+
|
|
61
|
+
- **Two severity modes**: `hard` blocks tokens completely (-inf logit), `bias` reduces probability by a configurable penalty
|
|
62
|
+
- **Strict mode**: forces end-of-sequence as soon as the generated prefix matches the start of a banned phrase, even before the full phrase is formed
|
|
63
|
+
- **GPU-accelerated pattern matching**: uses VectorizedAhoCorasick from the resklogits package for fast token scanning
|
|
64
|
+
- **Policy system**: YAML configuration associates capability bitmasks with phrase rules and tool permissions
|
|
65
|
+
- **Hot-reload**: PolicyWatcher detects file changes and rebuilds the automaton without restarting the server
|
|
66
|
+
- **Thread-safe cache**: automata are cached by (mask, model_name) with configurable TTL
|
|
67
|
+
- **Tool guard**: post-generation bitmask check for tool call execution
|
|
68
|
+
- **No JWT handling**: the package receives a raw integer bitmask; authentication and JWT decoding are handled by the calling application
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Requirements
|
|
73
|
+
|
|
74
|
+
- Python >= 3.13
|
|
75
|
+
- PyTorch >= 2.0.0
|
|
76
|
+
- transformers >= 4.35.0
|
|
77
|
+
- resklogits >= 0.1.0
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Installation
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install resksecure
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
[](https://pypi.org/project/resksecure/)
|
|
88
|
+
[](https://pypi.org/project/resksecure/)
|
|
89
|
+
|
|
90
|
+
From source:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
git clone https://github.com/Resk-Security/reskSecure.git
|
|
94
|
+
cd reskSecure
|
|
95
|
+
pip install -e .
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Quick start
|
|
101
|
+
|
|
102
|
+
Define a policy file (`policy.yaml`):
|
|
103
|
+
|
|
104
|
+
```yaml
|
|
105
|
+
version: "1.0"
|
|
106
|
+
policies:
|
|
107
|
+
- mask: 7
|
|
108
|
+
name: contributor
|
|
109
|
+
strict: false
|
|
110
|
+
default: true
|
|
111
|
+
rules:
|
|
112
|
+
- phrase: "DROP TABLE"
|
|
113
|
+
mode: hard
|
|
114
|
+
- phrase: "DELETE FROM"
|
|
115
|
+
mode: hard
|
|
116
|
+
- phrase: "salaries"
|
|
117
|
+
mode: bias
|
|
118
|
+
penalty: -5.0
|
|
119
|
+
tools:
|
|
120
|
+
read_email:
|
|
121
|
+
required_bit: 0
|
|
122
|
+
send_email:
|
|
123
|
+
required_bit: 1
|
|
124
|
+
read_sql:
|
|
125
|
+
required_bit: 2
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Use it in your generation pipeline:
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from resksecure import BitmaskLogitsProcessor, load_policy, verify_tool_action
|
|
132
|
+
|
|
133
|
+
policy_set = load_policy("policy.yaml")
|
|
134
|
+
|
|
135
|
+
processor = BitmaskLogitsProcessor(
|
|
136
|
+
mask=7,
|
|
137
|
+
model_name="mistralai/Mistral-7B-v0.1",
|
|
138
|
+
tokenizer=tokenizer,
|
|
139
|
+
policy_set=policy_set,
|
|
140
|
+
device="cuda",
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
outputs = model.generate(**inputs, logits_processor=[processor])
|
|
144
|
+
|
|
145
|
+
# Optional: verify tool calls against the bitmask
|
|
146
|
+
if has_tool_call(response):
|
|
147
|
+
if not verify_tool_action("send_email", user_mask=7, policy_set=policy_set):
|
|
148
|
+
raise PermissionError("Action not authorized")
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Policy reference
|
|
154
|
+
|
|
155
|
+
Policy-level fields:
|
|
156
|
+
|
|
157
|
+
| Field | Type | Description |
|
|
158
|
+
|-------------|---------|----------------------------------------------------------|
|
|
159
|
+
| `mask` | int | Capability bitmask that identifies this policy |
|
|
160
|
+
| `name` | string | Human-readable policy name |
|
|
161
|
+
| `strict` | bool | If true, stop generation at the first banned prefix |
|
|
162
|
+
| `default` | bool | If true, this policy is used when no exact mask matches |
|
|
163
|
+
| `rules` | list | List of phrase rules (see below) |
|
|
164
|
+
| `tools` | dict | Map of tool names to tool rule objects (see below) |
|
|
165
|
+
|
|
166
|
+
Phrase rule fields:
|
|
167
|
+
|
|
168
|
+
| Field | Type | Description |
|
|
169
|
+
|-----------|--------|------------------------------------------------------------|
|
|
170
|
+
| `phrase` | string | Text pattern to ban or penalize |
|
|
171
|
+
| `mode` | string | Either `hard` (block completely) or `bias` (reduce logits) |
|
|
172
|
+
| `penalty` | float | Logit penalty for bias mode (e.g. -5.0) |
|
|
173
|
+
|
|
174
|
+
Tool rule fields:
|
|
175
|
+
|
|
176
|
+
| Field | Type | Description |
|
|
177
|
+
|--------------------|----------|----------------------------------------------------------------|
|
|
178
|
+
| `required_bit` | int | Bit position that must be set in the user mask to use this tool |
|
|
179
|
+
| `trigger_phrases` | string[] | Phrases that start this tool call (blocked if bit not set) |
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Package structure
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
reskSecure/
|
|
187
|
+
src/resksecure/
|
|
188
|
+
__init__.py Public exports, version
|
|
189
|
+
policy_loader.py YAML parsing, Policy/PolicySet models
|
|
190
|
+
trie_factory.py Builds VectorizedAhoCorasick from a Policy
|
|
191
|
+
bitmask_processor.py BitmaskLogitsProcessor (LogitsProcessor subclass)
|
|
192
|
+
tool_guard.py Post-generation tool action verification
|
|
193
|
+
cache.py Thread-safe TTL cache for automata
|
|
194
|
+
policy_watcher.py Hot-reload daemon that watches YAML mtime
|
|
195
|
+
config/example_policy.yaml
|
|
196
|
+
tests/
|
|
197
|
+
examples/
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## License
|
|
203
|
+
|
|
204
|
+
This software is licensed under the RESK Software License. Commercial use requires a separate paid license. See the [LICENSE](LICENSE) file for details.
|
|
205
|
+
|
|
206
|
+
For commercial licensing inquiries, contact: contact@resk.fr
|