Verify + obfuscate: prove JAX/Flax inference code only does math (no data theft) while hiding the model architecture
Project description
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file syft_restrict-0.1.0.tar.gz.
File metadata
- Download URL: syft_restrict-0.1.0.tar.gz
- Upload date:
- Size: 55.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
207ee2cf543b1184fc6ec6ce7168fef26a51360a4198fb7ea37839498059ce7b
|
|
| MD5 |
8bdaa9ec8395ff62e87591e3f9c0f818
|
|
| BLAKE2b-256 |
2c224f4352c54ff76e8b369b1b9766384a483637d966dc356a7cc43186085994
|
File details
Details for the file syft_restrict-0.1.0-py3-none-any.whl.
File metadata
- Download URL: syft_restrict-0.1.0-py3-none-any.whl
- Upload date:
- Size: 29.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52382e4f86a6e9a43e9b2db1768a6d06cf717a389b423e6e81a492b19644e8ed
|
|
| MD5 |
3841783dc2ade636f938879e0a801350
|
|
| BLAKE2b-256 |
db1b4f4ed8f852e0ea0f2ae8dfead4c56270a746899e933aef81f2964435803f
|