modelaudit-picklescan 0.1.2__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.
- modelaudit_picklescan-0.1.2/CHANGELOG.md +94 -0
- modelaudit_picklescan-0.1.2/Cargo.lock +133 -0
- modelaudit_picklescan-0.1.2/Cargo.toml +23 -0
- modelaudit_picklescan-0.1.2/PKG-INFO +106 -0
- modelaudit_picklescan-0.1.2/README.md +79 -0
- modelaudit_picklescan-0.1.2/pyproject.toml +103 -0
- modelaudit_picklescan-0.1.2/rust/README.md +11 -0
- modelaudit_picklescan-0.1.2/rust/src/expansion.rs +309 -0
- modelaudit_picklescan-0.1.2/rust/src/lib.rs +21 -0
- modelaudit_picklescan-0.1.2/rust/src/nested.rs +1223 -0
- modelaudit_picklescan-0.1.2/rust/src/nested_surface.rs +143 -0
- modelaudit_picklescan-0.1.2/rust/src/opcode.rs +849 -0
- modelaudit_picklescan-0.1.2/rust/src/options.rs +100 -0
- modelaudit_picklescan-0.1.2/rust/src/policy.rs +276 -0
- modelaudit_picklescan-0.1.2/rust/src/post_budget.rs +616 -0
- modelaudit_picklescan-0.1.2/rust/src/pybridge.rs +34 -0
- modelaudit_picklescan-0.1.2/rust/src/report.rs +286 -0
- modelaudit_picklescan-0.1.2/rust/src/stack.rs +236 -0
- modelaudit_picklescan-0.1.2/rust/src/state.rs +4002 -0
- modelaudit_picklescan-0.1.2/rust/src/strings.rs +896 -0
- modelaudit_picklescan-0.1.2/rust/src/strings_policy.rs +79 -0
- modelaudit_picklescan-0.1.2/src/modelaudit_picklescan/__init__.py +21 -0
- modelaudit_picklescan-0.1.2/src/modelaudit_picklescan/api.py +1052 -0
- modelaudit_picklescan-0.1.2/src/modelaudit_picklescan/options.py +102 -0
- modelaudit_picklescan-0.1.2/src/modelaudit_picklescan/py.typed +1 -0
- modelaudit_picklescan-0.1.2/src/modelaudit_picklescan/report.py +202 -0
- modelaudit_picklescan-0.1.2/tests/conftest.py +8 -0
- modelaudit_picklescan-0.1.2/tests/parity_corpus.py +192 -0
- modelaudit_picklescan-0.1.2/tests/test_adversarial_pickle_oracle.py +302 -0
- modelaudit_picklescan-0.1.2/tests/test_api.py +2729 -0
- modelaudit_picklescan-0.1.2/tests/test_import_boundary.py +36 -0
- modelaudit_picklescan-0.1.2/tests/test_native_interface.py +48 -0
- modelaudit_picklescan-0.1.2/tests/test_options.py +55 -0
- modelaudit_picklescan-0.1.2/tests/test_report.py +167 -0
- modelaudit_picklescan-0.1.2/tests/test_rust_engine.py +367 -0
- modelaudit_picklescan-0.1.2/uv.lock +8 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `modelaudit-picklescan` will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this package adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.2](https://github.com/promptfoo/modelaudit/releases/tag/modelaudit-picklescan-v0.1.2) (2026-04-17)
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
|
|
12
|
+
- repair picklescan release wheel jobs ([#1051](https://github.com/promptfoo/modelaudit/issues/1051)) ([6c23190](https://github.com/promptfoo/modelaudit/commit/6c23190f9b23686d33d5da0a8b5522a59490084e))
|
|
13
|
+
|
|
14
|
+
## [0.1.1](https://github.com/promptfoo/modelaudit/releases/tag/modelaudit-picklescan-v0.1.1) (2026-04-17)
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
- extract standalone pickle scanner package with parity harness ([#832](https://github.com/promptfoo/modelaudit/issues/832)) ([e2986cd](https://github.com/promptfoo/modelaudit/commit/e2986cddaa592306cc10541865f011b3dc99a0ba))
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
- address code quality findings ([#1038](https://github.com/promptfoo/modelaudit/issues/1038)) ([7af03cf](https://github.com/promptfoo/modelaudit/commit/7af03cf42f33f1b255eb9f9cbcaac6caccd48bc1))
|
|
23
|
+
- bound standalone pickle stream reads ([4d0cb84](https://github.com/promptfoo/modelaudit/commit/4d0cb84af010b4ed332ebbf17fc8bd0769fa8b6e))
|
|
24
|
+
- **deps:** update rust crate pyo3 to 0.28.0 ([#1006](https://github.com/promptfoo/modelaudit/issues/1006)) ([fe93b47](https://github.com/promptfoo/modelaudit/commit/fe93b47c839588b3f33cfd21f4380306ec418f2a))
|
|
25
|
+
- detect hidden pytorch zip pickles ([#1043](https://github.com/promptfoo/modelaudit/issues/1043)) ([19b6ebe](https://github.com/promptfoo/modelaudit/commit/19b6ebe505d2ba90f81d6284d07e111f77cbf0b5))
|
|
26
|
+
- flag pickle persistent ids ([#938](https://github.com/promptfoo/modelaudit/issues/938)) ([2cfba40](https://github.com/promptfoo/modelaudit/commit/2cfba403e21d53f46ba7089b655cebc564dcddaf))
|
|
27
|
+
- harden pickle nested bypass detection ([#1027](https://github.com/promptfoo/modelaudit/issues/1027)) ([c3a3b9d](https://github.com/promptfoo/modelaudit/commit/c3a3b9d1e4ffbd854e6003afbf6ebef1e708a619))
|
|
28
|
+
- harden standalone pickle scanner ([#901](https://github.com/promptfoo/modelaudit/issues/901)) ([31f7dd3](https://github.com/promptfoo/modelaudit/commit/31f7dd38c6bd77631ccdca90438312c4db2ac857))
|
|
29
|
+
- narrow suspicious dunder string detection ([#947](https://github.com/promptfoo/modelaudit/issues/947)) ([e866760](https://github.com/promptfoo/modelaudit/commit/e8667609d293d4391205ce4e8884fa3559030604))
|
|
30
|
+
- preserve picklescan stack state ([#910](https://github.com/promptfoo/modelaudit/issues/910)) ([fabac5c](https://github.com/promptfoo/modelaudit/commit/fabac5c9ead49c2ed5f8357dfa53ccdcce946527))
|
|
31
|
+
|
|
32
|
+
### Documentation
|
|
33
|
+
|
|
34
|
+
- align markdown with current repo state ([#1035](https://github.com/promptfoo/modelaudit/issues/1035)) ([690bc52](https://github.com/promptfoo/modelaudit/commit/690bc5274198eb3428db9779ada0bdc2d40702ee))
|
|
35
|
+
|
|
36
|
+
## [Unreleased]
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- Introduce the Rust-native pickle scanning engine and standalone Python API package.
|
|
41
|
+
- Add `scan_bytes`, `scan_stream`, and `scan_file` entrypoints with typed immutable
|
|
42
|
+
reports for findings, notices, errors, coverage, verdict, and scan status.
|
|
43
|
+
- Add direct PyTorch ZIP container handling for `data.pkl` and other pickle
|
|
44
|
+
members, including per-member source locations and combined archive reports.
|
|
45
|
+
- Add detection coverage for dangerous pickle globals and executed calls,
|
|
46
|
+
malformed `STACK_GLOBAL` operands, copyreg extension references, persistent
|
|
47
|
+
IDs, `__main__` call escalation, `__dict__` import-only references, structural
|
|
48
|
+
tamper, protocol-5 external-buffer opcodes, and memo/`DUP` expansion patterns.
|
|
49
|
+
- Add nested-pickle detection for raw bytes plus base64, hex, escaped-hex, and
|
|
50
|
+
comment-wrapped encoded payloads, with recursive scans and bounded deep-scan
|
|
51
|
+
limits.
|
|
52
|
+
- Add suspicious string-literal matching for execution helpers, loader helpers,
|
|
53
|
+
`getattr` variants, `os.system`/`subprocess`/`runpy`/`webbrowser` patterns,
|
|
54
|
+
encoded code strings, and pickle loader references.
|
|
55
|
+
- Improve detection so dangerous globals and expansion patterns remain
|
|
56
|
+
reportable even when opcode-budget limits are reached.
|
|
57
|
+
- Add resource controls for timeout, opcode budget, post-budget byte scans,
|
|
58
|
+
known-size and unknown-size stream reads, long string literal probing, nested
|
|
59
|
+
pickle byte budgets, nested depth, and import-reference metadata volume.
|
|
60
|
+
- Add Python package tests, Rust unit tests, parity-corpus tests, wheel smoke
|
|
61
|
+
checks, Ruff, mypy, cargo fmt/check/clippy/test, MSRV check, and manylinux
|
|
62
|
+
release-wheel gates.
|
|
63
|
+
- Probe binary pickle operands for nested pickle streams while intentionally
|
|
64
|
+
leaving arbitrary non-pickle text extraction from BINBYTES/tensor blobs to the
|
|
65
|
+
root ModelAudit raw detector layer.
|
|
66
|
+
|
|
67
|
+
### Changed
|
|
68
|
+
|
|
69
|
+
- Use the Rust scanner as the only runtime engine; runtime engine selection and
|
|
70
|
+
Python-engine fallback behavior are not part of the public API.
|
|
71
|
+
- Release the Python GIL during native scans and avoid hot-path byte-literal
|
|
72
|
+
cloning by retaining borrowed payload spans for variable-length operands.
|
|
73
|
+
- Stream declared-size inputs in bounded chunks, normalize negative sizes as
|
|
74
|
+
unknown-size streams, cap both known-size and unbounded streams, and scan
|
|
75
|
+
partial bytes on declared-size short reads before returning an operational
|
|
76
|
+
error.
|
|
77
|
+
- Preserve standalone rule details while exposing ModelAudit-compatible rule
|
|
78
|
+
mappings for the root package, including dedicated nested-pickle, encoding,
|
|
79
|
+
persistent-ID, extension, structural-tamper, and expansion findings.
|
|
80
|
+
|
|
81
|
+
### Fixed
|
|
82
|
+
|
|
83
|
+
- Detect policy-backed dangerous globals in post-budget tails instead of relying
|
|
84
|
+
on a small hardcoded byte-needle table.
|
|
85
|
+
- Detect nested payloads that use PERSID/BINPERSID semantics, proto-0 payloads,
|
|
86
|
+
uppercase escaped-hex prefixes, multiline/comment-wrapped encodings, and long
|
|
87
|
+
literals with suspicious content outside prefix/suffix windows.
|
|
88
|
+
- Preserve stack state on operand underflow.
|
|
89
|
+
- Avoid wrapping MARK sentinels.
|
|
90
|
+
- Preserve `GLOBAL`/`INST` module/name operands without string roundtrips.
|
|
91
|
+
- Keep follow-on pickle streams at sibling depth.
|
|
92
|
+
- Cap import-reference metadata with an explicit notice, summarize repeated
|
|
93
|
+
persistent IDs, coalesce protocol-5 buffer notices, and surface structural
|
|
94
|
+
tamper severity without adapter downgrades.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 3
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "heck"
|
|
7
|
+
version = "0.5.0"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "libc"
|
|
13
|
+
version = "0.2.184"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af"
|
|
16
|
+
|
|
17
|
+
[[package]]
|
|
18
|
+
name = "modelaudit-picklescan-rust"
|
|
19
|
+
version = "0.1.2"
|
|
20
|
+
dependencies = [
|
|
21
|
+
"pyo3",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[[package]]
|
|
25
|
+
name = "once_cell"
|
|
26
|
+
version = "1.21.4"
|
|
27
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
28
|
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
29
|
+
|
|
30
|
+
[[package]]
|
|
31
|
+
name = "portable-atomic"
|
|
32
|
+
version = "1.13.1"
|
|
33
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
34
|
+
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
|
|
35
|
+
|
|
36
|
+
[[package]]
|
|
37
|
+
name = "proc-macro2"
|
|
38
|
+
version = "1.0.106"
|
|
39
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
40
|
+
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
|
41
|
+
dependencies = [
|
|
42
|
+
"unicode-ident",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[[package]]
|
|
46
|
+
name = "pyo3"
|
|
47
|
+
version = "0.28.3"
|
|
48
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
49
|
+
checksum = "91fd8e38a3b50ed1167fb981cd6fd60147e091784c427b8f7183a7ee32c31c12"
|
|
50
|
+
dependencies = [
|
|
51
|
+
"libc",
|
|
52
|
+
"once_cell",
|
|
53
|
+
"portable-atomic",
|
|
54
|
+
"pyo3-build-config",
|
|
55
|
+
"pyo3-ffi",
|
|
56
|
+
"pyo3-macros",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
[[package]]
|
|
60
|
+
name = "pyo3-build-config"
|
|
61
|
+
version = "0.28.3"
|
|
62
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
63
|
+
checksum = "e368e7ddfdeb98c9bca7f8383be1648fd84ab466bf2bc015e94008db6d35611e"
|
|
64
|
+
dependencies = [
|
|
65
|
+
"target-lexicon",
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
[[package]]
|
|
69
|
+
name = "pyo3-ffi"
|
|
70
|
+
version = "0.28.3"
|
|
71
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
72
|
+
checksum = "7f29e10af80b1f7ccaf7f69eace800a03ecd13e883acfacc1e5d0988605f651e"
|
|
73
|
+
dependencies = [
|
|
74
|
+
"libc",
|
|
75
|
+
"pyo3-build-config",
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
[[package]]
|
|
79
|
+
name = "pyo3-macros"
|
|
80
|
+
version = "0.28.3"
|
|
81
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
82
|
+
checksum = "df6e520eff47c45997d2fc7dd8214b25dd1310918bbb2642156ef66a67f29813"
|
|
83
|
+
dependencies = [
|
|
84
|
+
"proc-macro2",
|
|
85
|
+
"pyo3-macros-backend",
|
|
86
|
+
"quote",
|
|
87
|
+
"syn",
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
[[package]]
|
|
91
|
+
name = "pyo3-macros-backend"
|
|
92
|
+
version = "0.28.3"
|
|
93
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
94
|
+
checksum = "c4cdc218d835738f81c2338f822078af45b4afdf8b2e33cbb5916f108b813acb"
|
|
95
|
+
dependencies = [
|
|
96
|
+
"heck",
|
|
97
|
+
"proc-macro2",
|
|
98
|
+
"pyo3-build-config",
|
|
99
|
+
"quote",
|
|
100
|
+
"syn",
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
[[package]]
|
|
104
|
+
name = "quote"
|
|
105
|
+
version = "1.0.45"
|
|
106
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
107
|
+
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
|
108
|
+
dependencies = [
|
|
109
|
+
"proc-macro2",
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
[[package]]
|
|
113
|
+
name = "syn"
|
|
114
|
+
version = "2.0.117"
|
|
115
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
116
|
+
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
|
117
|
+
dependencies = [
|
|
118
|
+
"proc-macro2",
|
|
119
|
+
"quote",
|
|
120
|
+
"unicode-ident",
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
[[package]]
|
|
124
|
+
name = "target-lexicon"
|
|
125
|
+
version = "0.13.5"
|
|
126
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
127
|
+
checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
|
128
|
+
|
|
129
|
+
[[package]]
|
|
130
|
+
name = "unicode-ident"
|
|
131
|
+
version = "1.0.24"
|
|
132
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
133
|
+
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "modelaudit-picklescan-rust"
|
|
3
|
+
version = "0.1.2" # x-release-please-version
|
|
4
|
+
edition = "2021"
|
|
5
|
+
rust-version = "1.83"
|
|
6
|
+
description = "Native pickle security scanner engine for modelaudit-picklescan"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
repository = "https://github.com/promptfoo/modelaudit"
|
|
9
|
+
publish = false
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
|
|
12
|
+
[lib]
|
|
13
|
+
name = "modelaudit_picklescan_rust"
|
|
14
|
+
path = "rust/src/lib.rs"
|
|
15
|
+
crate-type = ["cdylib", "rlib"]
|
|
16
|
+
|
|
17
|
+
[features]
|
|
18
|
+
default = []
|
|
19
|
+
extension-module = ["pyo3/extension-module"]
|
|
20
|
+
abi3 = ["pyo3/abi3-py310"]
|
|
21
|
+
|
|
22
|
+
[dependencies]
|
|
23
|
+
pyo3 = { version = "0.28.0" }
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: modelaudit-picklescan
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Classifier: Development Status :: 3 - Alpha
|
|
5
|
+
Classifier: Intended Audience :: Developers
|
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
7
|
+
Classifier: Topic :: Security
|
|
8
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Summary: Standalone pickle security scanner extracted from ModelAudit
|
|
15
|
+
Keywords: pickle,security,model-scanning,ml
|
|
16
|
+
Author-email: Ian Webster <ian@promptfoo.dev>, Michael D'Angelo <michael@promptfoo.dev>, Yash Chhabria <yash@promptfoo.dev>
|
|
17
|
+
License: MIT
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
20
|
+
Project-URL: Changelog, https://github.com/promptfoo/modelaudit/blob/main/packages/modelaudit-picklescan/CHANGELOG.md
|
|
21
|
+
Project-URL: Documentation, https://github.com/promptfoo/modelaudit/tree/main/packages/modelaudit-picklescan
|
|
22
|
+
Project-URL: Homepage, https://github.com/promptfoo/modelaudit
|
|
23
|
+
Project-URL: Issues, https://github.com/promptfoo/modelaudit/issues
|
|
24
|
+
Project-URL: Repository, https://github.com/promptfoo/modelaudit
|
|
25
|
+
Project-URL: Security, https://github.com/promptfoo/modelaudit/security/policy
|
|
26
|
+
|
|
27
|
+
# modelaudit-picklescan
|
|
28
|
+
|
|
29
|
+
Standalone pickle security scanner package used by ModelAudit's pickle scanners.
|
|
30
|
+
|
|
31
|
+
This package is intentionally small: it exposes pickle byte/stream analysis,
|
|
32
|
+
safety verdicts, typed findings, and direct scanning of pickle members inside
|
|
33
|
+
common PyTorch ZIP checkpoints without importing the broader ModelAudit scanner
|
|
34
|
+
framework.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
The standalone `modelaudit-picklescan` wheel includes the Python API and the
|
|
39
|
+
native Rust scanner extension. The root `modelaudit` wheel depends on this
|
|
40
|
+
distribution so installed ModelAudit scans use the same native Rust scanner for
|
|
41
|
+
pickle payload analysis.
|
|
42
|
+
|
|
43
|
+
For local package work from a checkout, install the package directory directly:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
python -m pip install packages/modelaudit-picklescan
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Usage
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from modelaudit_picklescan import ScanOptions, scan_bytes, scan_file
|
|
53
|
+
|
|
54
|
+
report = scan_file("model.pt") # raw pickle files and PyTorch ZIP checkpoints
|
|
55
|
+
if report.has_security_findings:
|
|
56
|
+
for finding in report.findings:
|
|
57
|
+
print(finding.rule_code, finding.severity.value, finding.message)
|
|
58
|
+
|
|
59
|
+
report = scan_bytes(
|
|
60
|
+
payload,
|
|
61
|
+
source="archive.pt:data.pkl",
|
|
62
|
+
options=ScanOptions(
|
|
63
|
+
timeout_s=30.0,
|
|
64
|
+
max_opcodes=1_000_000,
|
|
65
|
+
max_string_literal_scan_chars=8 * 1024 * 1024,
|
|
66
|
+
max_nested_pickle_bytes=2 * 1024 * 1024,
|
|
67
|
+
max_nested_depth=2,
|
|
68
|
+
),
|
|
69
|
+
)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Native Scanner
|
|
73
|
+
|
|
74
|
+
The wheel includes a native Rust scanner for pickle payload analysis.
|
|
75
|
+
Nested pickle payload analysis is capped by byte budget and depth; the default
|
|
76
|
+
depth is 2 so common double-wrapped encoded pickle payloads are inspected while
|
|
77
|
+
recursive or adversarial nesting stays bounded.
|
|
78
|
+
Release wheels are published for Linux x86_64, Linux aarch64, macOS arm64,
|
|
79
|
+
macOS x86_64, and Windows targets. Other platforms may install from the source
|
|
80
|
+
distribution and need a local Rust toolchain available during install.
|
|
81
|
+
Use Rust 1.83+ when building from source.
|
|
82
|
+
|
|
83
|
+
## Report Contract
|
|
84
|
+
|
|
85
|
+
- `status`: scan completeness (`complete`, `inconclusive`, `error`)
|
|
86
|
+
- `verdict`: safety decision (`clean`, `suspicious`, `malicious`, `unknown`)
|
|
87
|
+
- `findings`: warning/critical security findings
|
|
88
|
+
- `notices`: informational coverage notes, including explicit partial-analysis
|
|
89
|
+
notices when literal or nested-pickle budgets are reached
|
|
90
|
+
- `errors`: operational failures
|
|
91
|
+
|
|
92
|
+
Notices are intended for explainability and audit trails. Aggregate dashboards
|
|
93
|
+
should treat `findings` at `warning` or `critical` severity as security alerts,
|
|
94
|
+
and group or count `notices` by code instead of presenting every INFO row as an
|
|
95
|
+
actionable issue.
|
|
96
|
+
|
|
97
|
+
Report mappings are read-only after construction. Use `to_dict()` when a mutable
|
|
98
|
+
plain-Python representation is needed.
|
|
99
|
+
|
|
100
|
+
## Package Boundary
|
|
101
|
+
|
|
102
|
+
`modelaudit-picklescan` analyzes raw pickle payloads and PyTorch ZIP checkpoint
|
|
103
|
+
pickle members. For full model-file routing, archive context, CLI output,
|
|
104
|
+
SARIF/export integrations, and broader scanner coverage, use the root
|
|
105
|
+
`modelaudit` package.
|
|
106
|
+
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# modelaudit-picklescan
|
|
2
|
+
|
|
3
|
+
Standalone pickle security scanner package used by ModelAudit's pickle scanners.
|
|
4
|
+
|
|
5
|
+
This package is intentionally small: it exposes pickle byte/stream analysis,
|
|
6
|
+
safety verdicts, typed findings, and direct scanning of pickle members inside
|
|
7
|
+
common PyTorch ZIP checkpoints without importing the broader ModelAudit scanner
|
|
8
|
+
framework.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
The standalone `modelaudit-picklescan` wheel includes the Python API and the
|
|
13
|
+
native Rust scanner extension. The root `modelaudit` wheel depends on this
|
|
14
|
+
distribution so installed ModelAudit scans use the same native Rust scanner for
|
|
15
|
+
pickle payload analysis.
|
|
16
|
+
|
|
17
|
+
For local package work from a checkout, install the package directory directly:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
python -m pip install packages/modelaudit-picklescan
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from modelaudit_picklescan import ScanOptions, scan_bytes, scan_file
|
|
27
|
+
|
|
28
|
+
report = scan_file("model.pt") # raw pickle files and PyTorch ZIP checkpoints
|
|
29
|
+
if report.has_security_findings:
|
|
30
|
+
for finding in report.findings:
|
|
31
|
+
print(finding.rule_code, finding.severity.value, finding.message)
|
|
32
|
+
|
|
33
|
+
report = scan_bytes(
|
|
34
|
+
payload,
|
|
35
|
+
source="archive.pt:data.pkl",
|
|
36
|
+
options=ScanOptions(
|
|
37
|
+
timeout_s=30.0,
|
|
38
|
+
max_opcodes=1_000_000,
|
|
39
|
+
max_string_literal_scan_chars=8 * 1024 * 1024,
|
|
40
|
+
max_nested_pickle_bytes=2 * 1024 * 1024,
|
|
41
|
+
max_nested_depth=2,
|
|
42
|
+
),
|
|
43
|
+
)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Native Scanner
|
|
47
|
+
|
|
48
|
+
The wheel includes a native Rust scanner for pickle payload analysis.
|
|
49
|
+
Nested pickle payload analysis is capped by byte budget and depth; the default
|
|
50
|
+
depth is 2 so common double-wrapped encoded pickle payloads are inspected while
|
|
51
|
+
recursive or adversarial nesting stays bounded.
|
|
52
|
+
Release wheels are published for Linux x86_64, Linux aarch64, macOS arm64,
|
|
53
|
+
macOS x86_64, and Windows targets. Other platforms may install from the source
|
|
54
|
+
distribution and need a local Rust toolchain available during install.
|
|
55
|
+
Use Rust 1.83+ when building from source.
|
|
56
|
+
|
|
57
|
+
## Report Contract
|
|
58
|
+
|
|
59
|
+
- `status`: scan completeness (`complete`, `inconclusive`, `error`)
|
|
60
|
+
- `verdict`: safety decision (`clean`, `suspicious`, `malicious`, `unknown`)
|
|
61
|
+
- `findings`: warning/critical security findings
|
|
62
|
+
- `notices`: informational coverage notes, including explicit partial-analysis
|
|
63
|
+
notices when literal or nested-pickle budgets are reached
|
|
64
|
+
- `errors`: operational failures
|
|
65
|
+
|
|
66
|
+
Notices are intended for explainability and audit trails. Aggregate dashboards
|
|
67
|
+
should treat `findings` at `warning` or `critical` severity as security alerts,
|
|
68
|
+
and group or count `notices` by code instead of presenting every INFO row as an
|
|
69
|
+
actionable issue.
|
|
70
|
+
|
|
71
|
+
Report mappings are read-only after construction. Use `to_dict()` when a mutable
|
|
72
|
+
plain-Python representation is needed.
|
|
73
|
+
|
|
74
|
+
## Package Boundary
|
|
75
|
+
|
|
76
|
+
`modelaudit-picklescan` analyzes raw pickle payloads and PyTorch ZIP checkpoint
|
|
77
|
+
pickle members. For full model-file routing, archive context, CLI output,
|
|
78
|
+
SARIF/export integrations, and broader scanner coverage, use the root
|
|
79
|
+
`modelaudit` package.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["maturin>=1.9,<2"]
|
|
3
|
+
build-backend = "maturin"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "modelaudit-picklescan"
|
|
7
|
+
version = "0.1.2" # x-release-please-version
|
|
8
|
+
description = "Standalone pickle security scanner extracted from ModelAudit"
|
|
9
|
+
authors = [
|
|
10
|
+
{ name = "Ian Webster", email = "ian@promptfoo.dev" },
|
|
11
|
+
{ name = "Michael D'Angelo", email = "michael@promptfoo.dev" },
|
|
12
|
+
{ name = "Yash Chhabria", email = "yash@promptfoo.dev" },
|
|
13
|
+
]
|
|
14
|
+
license = { text = "MIT" }
|
|
15
|
+
readme = "README.md"
|
|
16
|
+
keywords = ["pickle", "security", "model-scanning", "ml"]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 3 - Alpha",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Topic :: Security",
|
|
22
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Programming Language :: Python :: 3.10",
|
|
25
|
+
"Programming Language :: Python :: 3.11",
|
|
26
|
+
"Programming Language :: Python :: 3.12",
|
|
27
|
+
"Programming Language :: Python :: 3.13",
|
|
28
|
+
]
|
|
29
|
+
requires-python = ">=3.10"
|
|
30
|
+
dependencies = []
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://github.com/promptfoo/modelaudit"
|
|
34
|
+
Documentation = "https://github.com/promptfoo/modelaudit/tree/main/packages/modelaudit-picklescan"
|
|
35
|
+
Repository = "https://github.com/promptfoo/modelaudit"
|
|
36
|
+
Issues = "https://github.com/promptfoo/modelaudit/issues"
|
|
37
|
+
Changelog = "https://github.com/promptfoo/modelaudit/blob/main/packages/modelaudit-picklescan/CHANGELOG.md"
|
|
38
|
+
Security = "https://github.com/promptfoo/modelaudit/security/policy"
|
|
39
|
+
|
|
40
|
+
[tool.maturin]
|
|
41
|
+
python-source = "src"
|
|
42
|
+
module-name = "modelaudit_picklescan._rust"
|
|
43
|
+
features = ["extension-module", "abi3"]
|
|
44
|
+
|
|
45
|
+
[tool.ruff]
|
|
46
|
+
line-length = 120
|
|
47
|
+
target-version = "py310"
|
|
48
|
+
|
|
49
|
+
[tool.ruff.lint]
|
|
50
|
+
extend-select = [
|
|
51
|
+
"I",
|
|
52
|
+
"W",
|
|
53
|
+
"E",
|
|
54
|
+
"Q",
|
|
55
|
+
"COM",
|
|
56
|
+
"UP",
|
|
57
|
+
"B",
|
|
58
|
+
"C4",
|
|
59
|
+
"SIM",
|
|
60
|
+
"RUF",
|
|
61
|
+
]
|
|
62
|
+
ignore = [
|
|
63
|
+
"COM812",
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
[tool.ruff.lint.per-file-ignores]
|
|
67
|
+
"__init__.py" = ["F401"]
|
|
68
|
+
"tests/**/*.py" = ["S101", "F841"]
|
|
69
|
+
|
|
70
|
+
[tool.ruff.lint.flake8-quotes]
|
|
71
|
+
inline-quotes = "double"
|
|
72
|
+
multiline-quotes = "double"
|
|
73
|
+
docstring-quotes = "double"
|
|
74
|
+
avoid-escape = true
|
|
75
|
+
|
|
76
|
+
[tool.ruff.format]
|
|
77
|
+
quote-style = "double"
|
|
78
|
+
|
|
79
|
+
[tool.pytest.ini_options]
|
|
80
|
+
minversion = "7.0"
|
|
81
|
+
addopts = [
|
|
82
|
+
"-ra",
|
|
83
|
+
"--strict-markers",
|
|
84
|
+
"--strict-config",
|
|
85
|
+
"--disable-warnings",
|
|
86
|
+
"--tb=short",
|
|
87
|
+
]
|
|
88
|
+
testpaths = ["tests"]
|
|
89
|
+
|
|
90
|
+
[tool.mypy]
|
|
91
|
+
python_version = "3.10"
|
|
92
|
+
warn_return_any = true
|
|
93
|
+
warn_unused_configs = true
|
|
94
|
+
warn_redundant_casts = true
|
|
95
|
+
warn_unreachable = true
|
|
96
|
+
no_implicit_optional = true
|
|
97
|
+
strict_equality = true
|
|
98
|
+
show_error_codes = true
|
|
99
|
+
show_column_numbers = true
|
|
100
|
+
pretty = true
|
|
101
|
+
check_untyped_defs = true
|
|
102
|
+
disallow_incomplete_defs = true
|
|
103
|
+
ignore_missing_imports = true
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# modelaudit-picklescan Rust Engine
|
|
2
|
+
|
|
3
|
+
This directory contains the native scanner crate included in the
|
|
4
|
+
`modelaudit-picklescan` Python package.
|
|
5
|
+
|
|
6
|
+
For installation, Python API examples, supported report fields, and package
|
|
7
|
+
boundary details, see `../README.md`.
|
|
8
|
+
|
|
9
|
+
For contributor validation notes, see:
|
|
10
|
+
|
|
11
|
+
- `../../../docs/agents/picklescan-package-split.md`
|