syft-restrict
A static analyzer for Python source files that default-denies dynamic constructs in a private region, typically the model logic that must be kept private, while allowing the public region to be reviewed by the data owner in an obfuscated copy.
Overview
syft-restrict splits a Python file into two regions:
- Private — the lines the user marks as private, typically the model logic that
must not be readable. Mark them with
# syft-restrict: obfuscate-start/# syft-restrict: obfuscate-endor# syft-restrict: hide-start/# syft-restrict: hide-endcomments in the source. - Public — every other line outside the marked ranges: imports, data loading, wrappers. It is never checked or obfuscated. The recipient of the obfuscated file can read it directly.
Given that split, syft-restrict executes the following two steps:
- The verifier statically walks the private region and analyzes it against a default-deny policy. Every construct must be explicitly allowed, or verification fails and reports each offending line.
- The obfuscator runs after a clean verify. It creates an obfuscated copy by rewriting the private
region — renaming identifiers, blanking constants, replacing lines with
■■■■■■■■— so the logic can't be read back out, while the public region is copied through untouched.
The verifier is inspired by RestrictedPython, but differs in a few ways:
- It analyzes — it doesn't run. It never executes the source. Only the static checks decide pass/fail.
- The public code may import allowlisted libraries and call into them. Imports are not allowed in private code, and any library call must be explicitly allow-listed.
- Dynamic Python lives in the public part. Anything dynamic the author needs (file/tokenizer loading, the generation loop, wrappers around library methods) must be written in the public region — where it can be reviewed directly — and may be called by the private part.
Usage
Mark the private region in the source with comments:
# syft-restrict: obfuscate-start
def attention(x):
...
# syft-restrict: obfuscate-end
MODEL_ID = "gemma-2b" # syft-restrict: hide
See docs/verify.md for the full marker syntax (single-line markers, nesting rules, and error cases).
Then run:
import syft_restrict as restrict
result = restrict.run(
"gemma_inference.py",
allow_functions=["jax.*", "flax.linen.*"], # functions callable BY NAME (path-resolved)
allow_operators=["arithmetic", "indexing", "comparison"], # operators allowed ON A VALUE
)
# On success: writes gemma_inference.obfuscated.py and returns result.certificate.
# On a policy violation: raises PolicyViolation naming each offending line.
# If the file has no markers and obfuscate=/hide= are both omitted: raises MarkerError.
obfuscate=/hide= still work as an explicit escape hatch — pass either one (even an
empty list) and marker scanning is skipped entirely in favor of your own 1-based line
ranges:
result = restrict.run(
"gemma_inference.py",
obfuscate=[[22, 93], [99, 280]], # 1-based ranges: identifiers renamed, constants blanked
hide=[], # 1-based ranges: whole line replaced with ■■■■■■■■
allow_functions=["jax.*", "flax.linen.*"],
allow_operators=["arithmetic", "indexing", "comparison"],
)
This is how examples/gemma_inference.py generates examples/gemma_inference.obfuscated.py — see examples/generate.py.
The same model marked up with comment blocks instead of numeric ranges lives in examples/gemma_inference_marked.py / examples/generate_marked.py.
If syft-restrict was successfully executed on the true original file, the obfuscated file can be safely shared without exposing the private section.
Pass strict=False to run to get a RunResult with .ok / .violations
instead of an exception.
Documentation
- docs/verify.md — how verification works and what private code may do (allow side).
- docs/blacklist.md — default-deny catalog and violation codes (deny side).
- docs/code-layout.md — source modules and test layout.
Metadata
Release files for syft-restrict 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| syft_restrict-0.1.0.tar.gz | 55.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| syft_restrict-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 84.7 kB
Release files / syft_restrict-0.1.0.tar.gz
| Download URL | syft_restrict-0.1.0.tar.gz |
|---|---|
| Size | 55.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
207ee2cf543b1184fc6ec6ce7168fef26a51360a4198fb7ea37839498059ce7b
|
|
BLAKE2b-256 checksum How to use checksums |
2c224f4352c54ff76e8b369b1b9766384a483637d966dc356a7cc43186085994
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.8
|
Release files / syft_restrict-0.1.0-py3-none-any.whl
| Download URL | syft_restrict-0.1.0-py3-none-any.whl |
|---|---|
| Size | 29.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
52382e4f86a6e9a43e9b2db1768a6d06cf717a389b423e6e81a492b19644e8ed
|
|
BLAKE2b-256 checksum How to use checksums |
db1b4f4ed8f852e0ea0f2ae8dfead4c56270a746899e933aef81f2964435803f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.8
|