adaptersentry 1.0.3__tar.gz → 2.0.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.
Files changed (132) hide show
  1. adaptersentry-2.0.0/PKG-INFO +467 -0
  2. adaptersentry-2.0.0/README.md +223 -0
  3. adaptersentry-2.0.0/adaptersentry.egg-info/PKG-INFO +467 -0
  4. adaptersentry-2.0.0/adaptersentry.egg-info/SOURCES.txt +63 -0
  5. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/adaptersentry.egg-info/entry_points.txt +0 -1
  6. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/adaptersentry.egg-info/top_level.txt +0 -1
  7. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/benchmarks/corpus.py +3 -2
  8. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/benchmarks/harness.py +22 -14
  9. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/benchmarks/hub_scanner.py +144 -142
  10. adaptersentry-2.0.0/benchmarks/report.py +469 -0
  11. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/pyproject.toml +2 -2
  12. adaptersentry-2.0.0/src/adaptersentry/__init__.py +31 -0
  13. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/cli/batch.py +46 -61
  14. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/cli/main.py +9 -3
  15. adaptersentry-2.0.0/src/adaptersentry/cli/scan.py +92 -0
  16. adaptersentry-2.0.0/src/adaptersentry/detectors/__init__.py +1 -0
  17. adaptersentry-2.0.0/src/adaptersentry/detectors/intra_adapter.py +208 -0
  18. adaptersentry-2.0.0/src/adaptersentry/detectors/structural.py +200 -0
  19. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/engine/__init__.py +2 -4
  20. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/engine/cache.py +22 -3
  21. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/engine/orchestrator.py +19 -30
  22. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/engine/orchestrator_ray.py +22 -126
  23. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/engine/result_sink.py +12 -23
  24. adaptersentry-2.0.0/src/adaptersentry/engine/schemas/__init__.py +16 -0
  25. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/engine/schemas/combined_report.py +11 -11
  26. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/engine/schemas/identity.py +2 -39
  27. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/engine/schemas/requests.py +4 -0
  28. adaptersentry-2.0.0/src/adaptersentry/engine/worker.py +78 -0
  29. adaptersentry-2.0.0/src/adaptersentry/features/__init__.py +1 -0
  30. adaptersentry-2.0.0/src/adaptersentry/features/lowrank_core.py +213 -0
  31. adaptersentry-2.0.0/src/adaptersentry/features/spectral.py +207 -0
  32. adaptersentry-2.0.0/src/adaptersentry/parsers/__init__.py +15 -0
  33. adaptersentry-2.0.0/src/adaptersentry/parsers/adapter_config.py +229 -0
  34. adaptersentry-2.0.0/src/adaptersentry/parsers/adapter_file.py +240 -0
  35. adaptersentry-2.0.0/src/adaptersentry/parsers/names.py +106 -0
  36. adaptersentry-2.0.0/src/adaptersentry/parsers/safetensors.py +171 -0
  37. adaptersentry-2.0.0/src/adaptersentry/reporters/json.py +10 -0
  38. adaptersentry-2.0.0/src/adaptersentry/reporters/sarif.py +126 -0
  39. adaptersentry-2.0.0/src/adaptersentry/reporters/text.py +100 -0
  40. adaptersentry-2.0.0/src/adaptersentry/scanner.py +450 -0
  41. adaptersentry-2.0.0/src/adaptersentry/schemas/__init__.py +17 -0
  42. adaptersentry-2.0.0/src/adaptersentry/schemas/result.py +410 -0
  43. adaptersentry-2.0.0/src/adaptersentry/schemas/severity.py +14 -0
  44. adaptersentry-2.0.0/src/adaptersentry/scoring/__init__.py +1 -0
  45. adaptersentry-2.0.0/src/adaptersentry/scoring/verdict.py +126 -0
  46. adaptersentry-2.0.0/src/adaptersentry/version.py +1 -0
  47. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/tests/test_bench.py +245 -114
  48. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/tests/test_harness.py +18 -10
  49. adaptersentry-2.0.0/tests/test_scanner.py +200 -0
  50. adaptersentry-1.0.3/PKG-INFO +0 -748
  51. adaptersentry-1.0.3/README.md +0 -505
  52. adaptersentry-1.0.3/adaptersentry.egg-info/PKG-INFO +0 -748
  53. adaptersentry-1.0.3/adaptersentry.egg-info/SOURCES.txt +0 -99
  54. adaptersentry-1.0.3/benchmarks/report.py +0 -389
  55. adaptersentry-1.0.3/src/adaptersentry/__init__.py +0 -14
  56. adaptersentry-1.0.3/src/adaptersentry/analyzer.py +0 -638
  57. adaptersentry-1.0.3/src/adaptersentry/cli/scan.py +0 -307
  58. adaptersentry-1.0.3/src/adaptersentry/detectors/__init__.py +0 -27
  59. adaptersentry-1.0.3/src/adaptersentry/detectors/cross_layer.py +0 -112
  60. adaptersentry-1.0.3/src/adaptersentry/detectors/entropy.py +0 -93
  61. adaptersentry-1.0.3/src/adaptersentry/detectors/init_detector.py +0 -111
  62. adaptersentry-1.0.3/src/adaptersentry/detectors/outlier.py +0 -211
  63. adaptersentry-1.0.3/src/adaptersentry/detectors/wasserstein.py +0 -175
  64. adaptersentry-1.0.3/src/adaptersentry/engine/config.py +0 -137
  65. adaptersentry-1.0.3/src/adaptersentry/engine/feature_extractor.py +0 -561
  66. adaptersentry-1.0.3/src/adaptersentry/engine/schemas/__init__.py +0 -27
  67. adaptersentry-1.0.3/src/adaptersentry/engine/schemas/scan_result.py +0 -148
  68. adaptersentry-1.0.3/src/adaptersentry/engine/schemas/scoring.py +0 -104
  69. adaptersentry-1.0.3/src/adaptersentry/engine/schemas/signals.py +0 -90
  70. adaptersentry-1.0.3/src/adaptersentry/engine/worker.py +0 -371
  71. adaptersentry-1.0.3/src/adaptersentry/features/__init__.py +0 -6
  72. adaptersentry-1.0.3/src/adaptersentry/features/delta_norm.py +0 -232
  73. adaptersentry-1.0.3/src/adaptersentry/features/distribution.py +0 -234
  74. adaptersentry-1.0.3/src/adaptersentry/features/entropy_compression.py +0 -174
  75. adaptersentry-1.0.3/src/adaptersentry/features/inter_layer_similarity.py +0 -195
  76. adaptersentry-1.0.3/src/adaptersentry/features/layer_stats.py +0 -74
  77. adaptersentry-1.0.3/src/adaptersentry/features/tensor_stats.py +0 -139
  78. adaptersentry-1.0.3/src/adaptersentry/integrations/__init__.py +0 -1
  79. adaptersentry-1.0.3/src/adaptersentry/integrations/github_action.py +0 -97
  80. adaptersentry-1.0.3/src/adaptersentry/parsers/__init__.py +0 -24
  81. adaptersentry-1.0.3/src/adaptersentry/parsers/metadata.py +0 -172
  82. adaptersentry-1.0.3/src/adaptersentry/parsers/safetensors.py +0 -579
  83. adaptersentry-1.0.3/src/adaptersentry/reporters/json.py +0 -51
  84. adaptersentry-1.0.3/src/adaptersentry/reporters/sarif.py +0 -223
  85. adaptersentry-1.0.3/src/adaptersentry/reporters/text.py +0 -174
  86. adaptersentry-1.0.3/src/adaptersentry/reporting/human_summary.py +0 -295
  87. adaptersentry-1.0.3/src/adaptersentry/reporting/per_layer.py +0 -198
  88. adaptersentry-1.0.3/src/adaptersentry/schemas/__init__.py +0 -33
  89. adaptersentry-1.0.3/src/adaptersentry/schemas/adapter_metadata.py +0 -78
  90. adaptersentry-1.0.3/src/adaptersentry/schemas/adapter_report.py +0 -188
  91. adaptersentry-1.0.3/src/adaptersentry/schemas/confidence_score.py +0 -146
  92. adaptersentry-1.0.3/src/adaptersentry/schemas/distribution_features.py +0 -110
  93. adaptersentry-1.0.3/src/adaptersentry/schemas/entropy_compression_features.py +0 -117
  94. adaptersentry-1.0.3/src/adaptersentry/schemas/finding.py +0 -252
  95. adaptersentry-1.0.3/src/adaptersentry/schemas/inter_layer_similarity_features.py +0 -80
  96. adaptersentry-1.0.3/src/adaptersentry/schemas/norm_features.py +0 -64
  97. adaptersentry-1.0.3/src/adaptersentry/schemas/per_layer_finding.py +0 -73
  98. adaptersentry-1.0.3/src/adaptersentry/schemas/score_breakdown.py +0 -108
  99. adaptersentry-1.0.3/src/adaptersentry/schemas/scoring_policy.py +0 -99
  100. adaptersentry-1.0.3/src/adaptersentry/schemas/tensor_record.py +0 -125
  101. adaptersentry-1.0.3/src/adaptersentry/scoring/__init__.py +0 -6
  102. adaptersentry-1.0.3/src/adaptersentry/scoring/confidence.py +0 -231
  103. adaptersentry-1.0.3/src/adaptersentry/scoring/ensemble.py +0 -399
  104. adaptersentry-1.0.3/src/adaptersentry/scoring/risk_scorer.py +0 -128
  105. adaptersentry-1.0.3/src/adaptersentry/scoring/score_breakdown.py +0 -558
  106. adaptersentry-1.0.3/src/adaptersentry/scoring/verdict.py +0 -102
  107. adaptersentry-1.0.3/src/adaptersentry/version.py +0 -1
  108. adaptersentry-1.0.3/tests/test_analyzer.py +0 -98
  109. adaptersentry-1.0.3/tests/test_detectors.py +0 -245
  110. adaptersentry-1.0.3/tests/test_ensemble.py +0 -355
  111. adaptersentry-1.0.3/tests/test_init_detector.py +0 -203
  112. adaptersentry-1.0.3/tests/test_m1.py +0 -469
  113. adaptersentry-1.0.3/tests/test_m1_backward_compat.py +0 -125
  114. adaptersentry-1.0.3/tests/test_nonfinite_weights.py +0 -54
  115. adaptersentry-1.0.3/tests/test_risk_scorer.py +0 -202
  116. adaptersentry-1.0.3/tests/test_rust_extension.py +0 -33
  117. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/LICENSE +0 -0
  118. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/adaptersentry.egg-info/dependency_links.txt +0 -0
  119. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/adaptersentry.egg-info/requires.txt +0 -0
  120. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/benchmarks/__init__.py +0 -0
  121. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/benchmarks/check_regression.py +0 -0
  122. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/benchmarks/run_real.py +0 -0
  123. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/setup.cfg +0 -0
  124. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/__main__.py +0 -0
  125. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/cli/__init__.py +0 -0
  126. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/engine/identity.py +0 -0
  127. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/engine/manifest.py +0 -0
  128. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/engine/schemas/cache.py +0 -0
  129. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/reporters/__init__.py +0 -0
  130. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/reporting/__init__.py +0 -0
  131. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/reporting/sanitize.py +0 -0
  132. {adaptersentry-1.0.3 → adaptersentry-2.0.0}/src/adaptersentry/schemas/errors.py +0 -0
@@ -0,0 +1,467 @@
1
+ Metadata-Version: 2.4
2
+ Name: adaptersentry
3
+ Version: 2.0.0
4
+ Summary: Static security scanner for LoRA adapters — detects anomalous weight patterns in .safetensors files
5
+ License:
6
+ Apache License
7
+ Version 2.0, January 2004
8
+ http://www.apache.org/licenses/
9
+
10
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
11
+
12
+ 1. Definitions.
13
+
14
+ "License" shall mean the terms and conditions for use, reproduction,
15
+ and distribution as defined by Sections 1 through 9 of this document.
16
+
17
+ "Licensor" shall mean the copyright owner or entity authorized by
18
+ the copyright owner that is granting the License.
19
+
20
+ "Legal Entity" shall mean the union of the acting entity and all
21
+ other entities that control, are controlled by, or are under common
22
+ control with that entity. For the purposes of this definition,
23
+ "control" means (i) the power, direct or indirect, to cause the
24
+ direction or management of such entity, whether by contract or
25
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
26
+ outstanding shares, or (iii) beneficial ownership of such entity.
27
+
28
+ "You" (or "Your") shall mean an individual or Legal Entity
29
+ exercising permissions granted by this License.
30
+
31
+ "Source" form shall mean the preferred form for making modifications,
32
+ including but not limited to software source code, documentation
33
+ source, and configuration files.
34
+
35
+ "Object" form shall mean any form resulting from mechanical
36
+ transformation or translation of a Source form, including but
37
+ not limited to compiled object code, generated documentation,
38
+ and conversions to other media types.
39
+
40
+ "Work" shall mean the work of authorship, whether in Source or
41
+ Object form, made available under the License, as indicated by a
42
+ copyright notice that is included in or attached to the work
43
+ (an example is provided in the Appendix below).
44
+
45
+ "Derivative Works" shall mean any work, whether in Source or Object
46
+ form, that is based on (or derived from) the Work and for which the
47
+ editorial revisions, annotations, elaborations, or other modifications
48
+ represent, as a whole, an original work of authorship. For the purposes
49
+ of this License, Derivative Works shall not include works that remain
50
+ separable from, or merely link (or bind by name) to the interfaces of,
51
+ the Work and Derivative Works thereof.
52
+
53
+ "Contribution" shall mean any work of authorship, including
54
+ the original version of the Work and any modifications or additions
55
+ to that Work or Derivative Works thereof, that is intentionally
56
+ submitted to Licensor for inclusion in the Work by the copyright owner
57
+ or by an individual or Legal Entity authorized to submit on behalf of
58
+ the copyright owner. For the purposes of this definition, "submitted"
59
+ means any form of electronic, verbal, or written communication sent
60
+ to the Licensor or its representatives, including but not limited to
61
+ communication on electronic mailing lists, source code control systems,
62
+ and issue tracking systems that are managed by, or on behalf of, the
63
+ Licensor for the purpose of discussing and improving the Work, but
64
+ excluding communication that is conspicuously marked or otherwise
65
+ designated in writing by the copyright owner as "Not a Contribution."
66
+
67
+ "Contributor" shall mean Licensor and any individual or Legal Entity
68
+ on behalf of whom a Contribution has been received by Licensor and
69
+ subsequently incorporated within the Work.
70
+
71
+ 2. Grant of Copyright License. Subject to the terms and conditions of
72
+ this License, each Contributor hereby grants to You a perpetual,
73
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
74
+ copyright license to reproduce, prepare Derivative Works of,
75
+ publicly display, publicly perform, sublicense, and distribute the
76
+ Work and such Derivative Works in Source or Object form.
77
+
78
+ 3. Grant of Patent License. Subject to the terms and conditions of
79
+ this License, each Contributor hereby grants to You a perpetual,
80
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
81
+ (except as stated in this section) patent license to make, have made,
82
+ use, offer to sell, sell, import, and otherwise transfer the Work,
83
+ where such license applies only to those patent claims licensable
84
+ by such Contributor that are necessarily infringed by their
85
+ Contribution(s) alone or by combination of their Contribution(s)
86
+ with the Work to which such Contribution(s) was submitted. If You
87
+ institute patent litigation against any entity (including a
88
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
89
+ or a Contribution incorporated within the Work constitutes direct
90
+ or contributory patent infringement, then any patent licenses
91
+ granted to You under this License for that Work shall terminate
92
+ as of the date such litigation is filed.
93
+
94
+ 4. Redistribution. You may reproduce and distribute copies of the
95
+ Work or Derivative Works thereof in any medium, with or without
96
+ modifications, and in Source or Object form, provided that You
97
+ meet the following conditions:
98
+
99
+ (a) You must give any other recipients of the Work or
100
+ Derivative Works a copy of this License; and
101
+
102
+ (b) You must cause any modified files to carry prominent notices
103
+ stating that You changed the files; and
104
+
105
+ (c) You must retain, in the Source form of any Derivative Works
106
+ that You distribute, all copyright, patent, trademark, and
107
+ attribution notices from the Source form of the Work,
108
+ excluding those notices that do not pertain to any part of
109
+ the Derivative Works; and
110
+
111
+ (d) If the Work includes a "NOTICE" text file as part of its
112
+ distribution, then any Derivative Works that You distribute must
113
+ include a readable copy of the attribution notices contained
114
+ within such NOTICE file, excluding those notices that do not
115
+ pertain to any part of the Derivative Works, in at least one
116
+ of the following places: within a NOTICE text file distributed
117
+ as part of the Derivative Works; within the Source form or
118
+ documentation, if provided along with the Derivative Works; or,
119
+ within a display generated by the Derivative Works, if and
120
+ wherever such third-party notices normally appear. The contents
121
+ of the NOTICE file are for informational purposes only and
122
+ do not modify the License. You may add Your own attribution
123
+ notices within Derivative Works that You distribute, alongside
124
+ or as an addendum to the NOTICE text from the Work, provided
125
+ that such additional attribution notices cannot be construed
126
+ as modifying the License.
127
+
128
+ You may add Your own copyright statement to Your modifications and
129
+ may provide additional or different license terms and conditions
130
+ for use, reproduction, or distribution of Your modifications, or
131
+ for any such Derivative Works as a whole, provided Your use,
132
+ reproduction, and distribution of the Work otherwise complies with
133
+ the conditions stated in this License.
134
+
135
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
136
+ any Contribution intentionally submitted for inclusion in the Work
137
+ by You to the Licensor shall be under the terms and conditions of
138
+ this License, without any additional terms or conditions.
139
+ Notwithstanding the above, nothing herein shall supersede or modify
140
+ the terms of any separate license agreement you may have executed
141
+ with Licensor regarding such Contributions.
142
+
143
+ 6. Trademarks. This License does not grant permission to use the trade
144
+ names, trademarks, service marks, or product names of the Licensor,
145
+ except as required for reasonable and customary use in describing the
146
+ origin of the Work and reproducing the content of the NOTICE file.
147
+
148
+ 7. Disclaimer of Warranty. Unless required by applicable law or
149
+ agreed to in writing, Licensor provides the Work (and each
150
+ Contributor provides its Contributions) on an "AS IS" BASIS,
151
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
152
+ implied, including, without limitation, any warranties or conditions
153
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
154
+ PARTICULAR PURPOSE. You are solely responsible for determining the
155
+ appropriateness of using or redistributing the Work and assume any
156
+ risks associated with Your exercise of permissions under this License.
157
+
158
+ 8. Limitation of Liability. In no event and under no legal theory,
159
+ whether in tort (including negligence), contract, or otherwise,
160
+ unless required by applicable law (such as deliberate and grossly
161
+ negligent acts) or agreed to in writing, shall any Contributor be
162
+ liable to You for damages, including any direct, indirect, special,
163
+ incidental, or consequential damages of any character arising as a
164
+ result of this License or out of the use or inability to use the
165
+ Work (including but not limited to damages for loss of goodwill,
166
+ work stoppage, computer failure or malfunction, or any and all
167
+ other commercial damages or losses), even if such Contributor
168
+ has been advised of the possibility of such damages.
169
+
170
+ 9. Accepting Warranty or Additional Liability. While redistributing
171
+ the Work or Derivative Works thereof, You may choose to offer,
172
+ and charge a fee for, acceptance of support, warranty, indemnity,
173
+ or other liability obligations and/or rights consistent with this
174
+ License. However, in accepting such obligations, You may act only
175
+ on Your own behalf and on Your sole responsibility, not on behalf
176
+ of any other Contributor, and only if You agree to indemnify,
177
+ defend, and hold each Contributor harmless for any liability
178
+ incurred by, or claims asserted against, such Contributor by reason
179
+ of your accepting any such warranty or additional liability.
180
+
181
+ END OF TERMS AND CONDITIONS
182
+
183
+ APPENDIX: How to apply the Apache License to your work.
184
+
185
+ To apply the Apache License to your work, attach the following
186
+ boilerplate notice, with the fields enclosed by brackets "[]"
187
+ replaced with your own identifying information. (Don't include
188
+ the brackets!) The text should be enclosed in the appropriate
189
+ comment syntax for the file format. We also recommend that a
190
+ file or class name and description of purpose be included on the
191
+ same "printed page" as the copyright notice for easier
192
+ identification within third-party archives.
193
+
194
+ Copyright 2026 Nikita Korvyakov
195
+
196
+ Licensed under the Apache License, Version 2.0 (the "License");
197
+ you may not use this file except in compliance with the License.
198
+ You may obtain a copy of the License at
199
+
200
+ http://www.apache.org/licenses/LICENSE-2.0
201
+
202
+ Unless required by applicable law or agreed to in writing, software
203
+ distributed under the License is distributed on an "AS IS" BASIS,
204
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
205
+ See the License for the specific language governing permissions and
206
+ limitations under the License.
207
+
208
+ Project-URL: Homepage, https://github.com/nkorvyakov28-AS/adaptersentry-m1
209
+ Project-URL: Documentation, https://github.com/nkorvyakov28-AS/adaptersentry-m1/tree/main/docs
210
+ Project-URL: Repository, https://github.com/nkorvyakov28-AS/adaptersentry-m1
211
+ Project-URL: Bug Tracker, https://github.com/nkorvyakov28-AS/adaptersentry-m1/issues
212
+ Project-URL: Changelog, https://github.com/nkorvyakov28-AS/adaptersentry-m1/blob/main/CHANGELOG.md
213
+ Keywords: security,llm,lora,adapter,safetensors,malware-detection,static-analysis
214
+ Classifier: Development Status :: 4 - Beta
215
+ Classifier: Intended Audience :: Developers
216
+ Classifier: Intended Audience :: Science/Research
217
+ Classifier: License :: OSI Approved :: Apache Software License
218
+ Classifier: Programming Language :: Python :: 3
219
+ Classifier: Programming Language :: Python :: 3.11
220
+ Classifier: Programming Language :: Python :: 3.12
221
+ Classifier: Programming Language :: Python :: 3.13
222
+ Classifier: Programming Language :: Python :: 3.14
223
+ Classifier: Topic :: Security
224
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
225
+ Classifier: Typing :: Typed
226
+ Requires-Python: >=3.11
227
+ Description-Content-Type: text/markdown
228
+ License-File: LICENSE
229
+ Requires-Dist: safetensors<1,>=0.4.0
230
+ Requires-Dist: numpy<3,>=2.0
231
+ Requires-Dist: scipy<2,>=1.13
232
+ Requires-Dist: scikit-learn<2,>=1.5
233
+ Requires-Dist: pydantic<3,>=2.5.0
234
+ Requires-Dist: rich<16,>=13.0.0
235
+ Provides-Extra: bench
236
+ Requires-Dist: huggingface_hub<2,>=0.20.0; extra == "bench"
237
+ Requires-Dist: psutil<8,>=5.9.0; extra == "bench"
238
+ Provides-Extra: dev
239
+ Requires-Dist: adaptersentry[bench]; extra == "dev"
240
+ Requires-Dist: pytest<10,>=7.4.0; extra == "dev"
241
+ Provides-Extra: ray
242
+ Requires-Dist: ray[default]<3,>=2.9.0; extra == "ray"
243
+ Dynamic: license-file
244
+
245
+ # AdapterSentry
246
+
247
+ ![Python](https://img.shields.io/badge/python-%3E%3D3.11-blue)
248
+ ![License](https://img.shields.io/badge/license-Apache%202.0-blue)
249
+ ![Version](https://img.shields.io/badge/version-2.0.0-blue)
250
+
251
+ AdapterSentry is a static security scanner for LoRA adapters distributed as `.safetensors`
252
+ files. A LoRA adapter is a small file that changes how a large language model behaves; anyone
253
+ can publish one, and a poisoned adapter can carry a backdoor that stays silent until a trigger
254
+ appears in the input. AdapterSentry inspects the adapter's weights **before** the adapter is
255
+ loaded, without running the model and without knowing the trigger.
256
+
257
+ **v2.0.0** replaces the analysis engine: exact statistics of the effective update
258
+ ΔW = s·B·A (no sampling, no proxies), streaming analysis that scales to 70B–405B and MoE
259
+ models in tens of megabytes of memory, a comparison of every module with its own family inside
260
+ the adapter, structural findings, and a new result contract (`ScanResult 2.0.0`).
261
+ See [CHANGELOG.md](CHANGELOG.md) and [Migrating from 1.x](#migrating-from-1x).
262
+
263
+ ---
264
+
265
+ ## What it tells you
266
+
267
+ ```text
268
+ $ adaptersentry scan adapter_model.safetensors
269
+ AdapterSentry 2.0.0 · adapter_model.safetensors
270
+ ================================================================
271
+ Verdict: REVIEW (MEDIUM) · confidence medium · behavioural check recommended
272
+ Status: ok · policy default · mode full
273
+ Why:
274
+ - [LOW] NO_REFERENCE_PROFILE: No calibrated reference for this model family; verdict relies on intra-adapter comparison
275
+ - [MEDIUM] INTRA_OUTLIER: Module departs from its family: down_proj layer 47, robust z = 9.4 (threshold 8.0, uncalibrated)
276
+ Adapter: peft_lora, family llama (config), 80 layers, r=64 (declared 64), α=128, scaling alpha_over_r, training trained
277
+ Coverage: 560/560 modules analysed; 0 tensor(s) not analysed
278
+ Intra: max robust z 9.4 · 2 outlier module(s) · energy Gini 0.41
279
+ Findings (1):
280
+ [MEDIUM] INTRA_DEPTH_SPIKE — Module departs from its family (layer 47, down_proj)
281
+ ```
282
+ *(Illustrative output.)*
283
+
284
+ The verdict is one of **`allow`**, **`review`** or **`block`**, with the reasons, a confidence
285
+ level and what limits it. CI gates read `verdict.action`.
286
+
287
+ ---
288
+
289
+ ## Quick start
290
+
291
+ ```bash
292
+ pip install adaptersentry
293
+
294
+ adaptersentry scan adapter_model.safetensors # text summary
295
+ adaptersentry scan adapter_model.safetensors --format json # ScanResult 2.0.0
296
+ adaptersentry scan adapter_model.safetensors --format sarif \
297
+ --output adaptersentry.sarif --fail-on review # GitHub code scanning + CI gate
298
+ adaptersentry batch --input-dir adapters/ --workers 8 --fail-on review
299
+ ```
300
+
301
+ ```python
302
+ from pathlib import Path
303
+ from adaptersentry import scan
304
+
305
+ result = scan(Path("adapter_model.safetensors"))
306
+ print(result.verdict.action, result.verdict.level)
307
+ for reason in result.verdict.reasons:
308
+ print(reason.code, reason.message)
309
+ ```
310
+
311
+ Put `adapter_config.json` next to the `.safetensors` file (as PEFT saves it): the scan needs
312
+ `lora_alpha` to know the real size of the update.
313
+
314
+ | Option | Meaning |
315
+ |---|---|
316
+ | `--format text\|json\|full-json\|sarif` | output; `full-json` adds per-module features |
317
+ | `--policy default\|strict` | `strict` blocks on structural red flags (see below) |
318
+ | `--fail-on review\|block` | exit code 2 if the verdict reaches this action |
319
+ | `--mode full\|fast` | `fast` uses fewer samples for the kurtosis estimate |
320
+ | `--include-modules`, `--include-heads` | per-module / per-attention-head detail in JSON |
321
+ | `--full-paths` | report the absolute path instead of the file name |
322
+
323
+ Exit codes: `0` completed, `1` the adapter could not be analysed (the verdict is still
324
+ `review`), `2` the `--fail-on` threshold was reached.
325
+
326
+ ---
327
+
328
+ ## How it works
329
+
330
+ ```
331
+ file ─► validate ─► inventory ─► per module (streamed) ─► compare within ─► structural ─► verdict
332
+ header every exact ΔW features each module findings
333
+ & limits tensor via r×r cores family
334
+ ```
335
+
336
+ 1. **Validate before reading.** The file must be a regular `.safetensors` file; the header
337
+ length, dtype, shape, byte ranges, element counts and LoRA rank are checked from the header
338
+ before any tensor is allocated.
339
+ 2. **Inventory.** Every tensor is classified: LoRA A/B pairs (with layer, expert and module),
340
+ full weights shipped via `modules_to_save`, DoRA vectors, trainable-token deltas, and
341
+ anything that cannot be analysed — nothing is skipped silently.
342
+ 3. **Exact features, one module at a time.** For ΔW = s·B·A, where s = α/r (or α/√r with
343
+ rsLoRA) comes from `adapter_config.json`, the singular values, norms and row/column norms
344
+ are computed exactly through the r×r matrices AAᵀ and BᵀB — ΔW itself (235 M values for a
345
+ 70B MLP layer) is never built. Features describe the **shape** of the update, which the
346
+ literature finds informative, rather than its size:
347
+ stable rank, participation ratio, spectral entropy, concentration of the leading direction
348
+ versus a random baseline, entry kurtosis (estimated by importance sampling of rows so rare
349
+ spiky rows are not missed), and how concentrated the update is on a few output rows or
350
+ input columns — for `lm_head` and embeddings, on a few tokens.
351
+ 4. **Compare within the adapter.** Each module is compared with its family (all `q_proj`, all
352
+ `down_proj`, …): the smooth trend with depth is removed with a Theil–Sen line, then robust
353
+ z-scores (median/MAD) mark modules that depart from their family. This needs no reference
354
+ data and is insensitive to the adapter's overall strength. It runs for families of at
355
+ least 16 modules.
356
+ 5. **Structural findings** that numbers cannot show: complete `lm_head` / embedding / router
357
+ matrices shipped in the adapter, LoRA on a mixture-of-experts router, ranks that differ from
358
+ the declared `r` (typical of merged adapters), code/pickle/archive files next to the adapter.
359
+ 6. **Verdict** — one rule set, fail-closed:
360
+
361
+ | Situation | Action |
362
+ |---|---|
363
+ | File could not be parsed, or part of it was not analysed | at least `review` |
364
+ | A module departs from its family (robust z ≥ 8) | `review` |
365
+ | Structural red flag | `review`; `block` with `--policy strict` |
366
+ | Reference profile for the model family says p ≤ α | `review` / `block` *(reference profiles: next release)* |
367
+ | Otherwise | `allow` |
368
+
369
+ Without a calibrated reference profile the default policy never blocks: the false-positive
370
+ rate of a block would be unknown.
371
+
372
+ ### Performance
373
+
374
+ Measured on an 8-CPU server with a synthetic Llama-3.3-70B-shaped adapter
375
+ (80 layers × 7 modules, r = 64, 1.66 GB bf16): `adaptersentry scan` end to end in
376
+ **~18–20 s**, peak process memory **~160 MB** (Python and numpy included). The 1.x engine
377
+ needed ~3.3 GB just to load the same file.
378
+
379
+ ---
380
+
381
+ ## Limits — read before relying on a verdict
382
+
383
+ - **Static analysis is a first filter, not a proof.** Research on weight-space detection
384
+ shows strong results in the lab and clear limits: detectors trained on known attacks fail on
385
+ new ones, and on larger models the variation between honest adapters trained with different
386
+ random seeds can exceed the signal of a backdoor. A low-risk verdict is not evidence that an
387
+ adapter is safe; behavioural verification in an isolated environment remains necessary for
388
+ adapters you do not trust.
389
+ - **Thresholds are not yet calibrated.** Intra-adapter thresholds (|z| > 3.5 outlier,
390
+ ≥ 8 review) were set on synthetic data. Reference profiles per model family and a measured
391
+ detection rate on labelled clean/poisoned adapters are the next step; until then the
392
+ confidence of a verdict is at most `medium`.
393
+ - **An attacker who knows the detector** can try to spread a backdoor across many directions
394
+ and modules, or pad the update with inert components. Static analysis without base-model
395
+ information cannot fully rule this out.
396
+ - **Not analysed:** full weight matrices (they need the base model), trainable-token deltas;
397
+ DoRA adapters are analysed partially. Each of these is reported and lowers the verdict's
398
+ confidence or raises it to `review`.
399
+ - **Pickle-based formats** (`.bin`, `.pt`) are never deserialised. Use a dedicated
400
+ serialisation scanner for them.
401
+
402
+ ---
403
+
404
+ ## Output: ScanResult 2.0.0
405
+
406
+ `--format json` produces one document per adapter: `scan` (who/when/how), `artifact` (hashes,
407
+ provenance — file name only unless `--full-paths`), `adapter` (format, family, rank, α,
408
+ scaling, modules), `status` + `coverage` (what was and was not analysed), `verdict`,
409
+ `anomaly` (what the verdict rests on), `findings` (with exact layer/module/tensor locations),
410
+ optional `modules`, and `errors`.
411
+
412
+ - Field reference: [docs/output-schema/scan-result.md](docs/output-schema/scan-result.md)
413
+ - JSON Schema: [docs/output-schema/scan-result-2.0.0.schema.json](docs/output-schema/scan-result-2.0.0.schema.json)
414
+ - `adaptersentry.load_scan_result()` validates a document and rejects other major versions.
415
+
416
+ ---
417
+
418
+ ## Migrating from 1.x
419
+
420
+ | 1.x | 2.0.0 |
421
+ |---|---|
422
+ | `analyze()`, `scan()` → `AdapterReport`, `scan_to_result()` | `scan()` → `ScanResult` |
423
+ | `verdict.recommended_action` | `verdict.action` |
424
+ | `overall_score`, `ensemble.score` (0–100) | removed — `verdict.level` + `anomaly` (z-scores, later p-values) |
425
+ | `status`, `parse_status`, `analysis_mode` | `status` + `coverage` |
426
+ | `--format summary-json` / `debug-json` | `--format json` / `full-json` |
427
+ | `--fail-on LOW…CRITICAL` (finding severity) | `--fail-on review\|block` (verdict action) |
428
+ | `--rank` | removed — rank is read from the tensors and checked against the config |
429
+ | `adaptersentry-m1` command | `adaptersentry scan` |
430
+
431
+ 1.x results are not converted: re-scan the adapters.
432
+
433
+ ---
434
+
435
+ ## Development
436
+
437
+ ```bash
438
+ git clone https://github.com/nkorvyakov28-AS/adaptersentry-m1
439
+ cd adaptersentry-m1
440
+ uv sync --frozen --extra dev # or: pip install -e ".[dev]"
441
+ pytest tests/ -q
442
+ ```
443
+
444
+ Architecture: [docs/architecture/m1-architecture.md](docs/architecture/m1-architecture.md) ·
445
+ CLI: [docs/cli/usage.md](docs/cli/usage.md) · Batch engine:
446
+ [docs/architecture/scan-engine.md](docs/architecture/scan-engine.md)
447
+
448
+ AdapterSentry M1 is the open static-analysis layer. Planned: M2 Behavioral Sandbox — advanced
449
+ behavioral analysis.
450
+
451
+ ## Background
452
+
453
+ The feature design follows published work on weight-space backdoor detection in LoRA adapters,
454
+ including *Detecting Backdoored LoRAs from Weights Alone* (arXiv:2602.15195),
455
+ *Token-Level Generalization in LoRA Adapter Backdoors* (arXiv:2605.30189) and Z-PEFT
456
+ (arXiv:2608.02271). Their results motivate the choices above: shape over magnitude,
457
+ per-module and per-head features, MLP coverage, and one-class calibration instead of a
458
+ classifier trained on known attacks.
459
+
460
+ ## Security
461
+
462
+ See [SECURITY.md](SECURITY.md). Report a malicious adapter found in the wild with a GitHub
463
+ issue labelled `malicious-adapter`; report vulnerabilities in AdapterSentry privately.
464
+
465
+ ## License
466
+
467
+ Apache 2.0 — see [LICENSE](LICENSE).