modelaudit 0.2.30__tar.gz → 0.2.32__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 (601) hide show
  1. {modelaudit-0.2.30 → modelaudit-0.2.32}/.github/workflows/README.md +1 -1
  2. {modelaudit-0.2.30 → modelaudit-0.2.32}/.github/workflows/perf.yml +66 -33
  3. modelaudit-0.2.32/.release-please-manifest.json +3 -0
  4. {modelaudit-0.2.30 → modelaudit-0.2.32}/AGENTS.md +2 -4
  5. {modelaudit-0.2.30 → modelaudit-0.2.32}/CHANGELOG.md +92 -0
  6. modelaudit-0.2.32/CLAUDE.md +1 -0
  7. {modelaudit-0.2.30 → modelaudit-0.2.32}/PKG-INFO +1 -1
  8. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/cli.py +0 -3
  9. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/core.py +18 -4
  10. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/detectors/jit_script.py +5 -1
  11. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/detectors/secrets.py +4 -2
  12. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/integrations/license_checker.py +59 -28
  13. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/models.py +17 -1
  14. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/progress/base.py +0 -4
  15. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/progress/file.py +0 -1
  16. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/progress/hooks.py +0 -6
  17. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/__init__.py +3 -4
  18. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/base.py +0 -1
  19. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/compressed_scanner.py +44 -28
  20. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/coreml_scanner.py +442 -105
  21. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/flax_msgpack_scanner.py +115 -57
  22. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/gguf_scanner.py +8 -20
  23. modelaudit-0.2.32/modelaudit/scanners/jax_checkpoint_scanner.py +1092 -0
  24. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/joblib_scanner.py +126 -48
  25. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/keras_h5_scanner.py +190 -81
  26. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/keras_zip_scanner.py +191 -38
  27. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/nemo_scanner.py +60 -33
  28. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/oci_layer_scanner.py +199 -22
  29. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/onnx_scanner.py +128 -19
  30. modelaudit-0.2.32/modelaudit/scanners/openvino_scanner.py +251 -0
  31. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/pickle_scanner.py +442 -76
  32. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/pmml_scanner.py +90 -28
  33. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/pytorch_binary_scanner.py +71 -18
  34. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/pytorch_zip_scanner.py +182 -65
  35. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/sevenzip_scanner.py +100 -29
  36. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/skops_scanner.py +35 -15
  37. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/tar_scanner.py +67 -42
  38. modelaudit-0.2.32/modelaudit/scanners/tensorrt_scanner.py +109 -0
  39. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/tf_metagraph_scanner.py +51 -14
  40. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/tf_savedmodel_scanner.py +65 -12
  41. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/tflite_scanner.py +103 -58
  42. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/torchserve_mar_scanner.py +490 -206
  43. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/zip_scanner.py +71 -24
  44. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/file/detection.py +180 -16
  45. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/helpers/ml_context.py +3 -2
  46. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/helpers/result_conversion.py +4 -0
  47. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/helpers/secure_hasher.py +0 -2
  48. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/helpers/types.py +42 -0
  49. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/sources/jfrog.py +4 -4
  50. {modelaudit-0.2.30 → modelaudit-0.2.32}/pyproject.toml +1 -1
  51. modelaudit-0.2.32/scripts/benchmark_report.py +307 -0
  52. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/analysis/test_entropy_analyzer.py +4 -4
  53. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/benchmarks/test_scan_benchmarks.py +17 -9
  54. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/conftest.py +121 -28
  55. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/detectors/test_jit_script_detector.py +9 -8
  56. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/integrations/test_license_checker.py +29 -0
  57. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_compressed_scanner.py +38 -0
  58. modelaudit-0.2.32/tests/scanners/test_coreml_scanner.py +648 -0
  59. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_flax_msgpack_scanner.py +125 -19
  60. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_gguf_scanner.py +37 -0
  61. modelaudit-0.2.32/tests/scanners/test_jax_checkpoint_scanner.py +838 -0
  62. modelaudit-0.2.32/tests/scanners/test_joblib_scanner_codecs.py +153 -0
  63. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_keras_h5_scanner.py +239 -3
  64. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_keras_zip_scanner.py +260 -0
  65. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_nemo_scanner.py +104 -7
  66. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_oci_layer_scanner.py +233 -17
  67. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_onnx_dependency_handling.py +3 -2
  68. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_onnx_scanner.py +245 -18
  69. modelaudit-0.2.32/tests/scanners/test_openvino_scanner.py +222 -0
  70. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_pickle_scanner.py +574 -6
  71. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_pmml_scanner.py +203 -0
  72. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_pytorch_binary_scanner.py +85 -1
  73. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_pytorch_zip_scanner.py +73 -0
  74. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_scanner_registry.py +1 -0
  75. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_sevenzip_scanner.py +124 -14
  76. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_skops_scanner.py +33 -0
  77. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_tar_scanner.py +65 -4
  78. modelaudit-0.2.32/tests/scanners/test_tensorrt_scanner.py +148 -0
  79. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_tf_metagraph_scanner.py +123 -14
  80. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_tf_savedmodel_scanner.py +190 -0
  81. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_tflite_scanner.py +70 -0
  82. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_torchserve_mar_scanner.py +754 -3
  83. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_xgboost_scanner.py +2 -2
  84. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_zip_scanner.py +86 -10
  85. modelaudit-0.2.32/tests/test_benchmark_report.py +355 -0
  86. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_cache_optimizations.py +21 -6
  87. modelaudit-0.2.32/tests/test_core.py +619 -0
  88. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_integration.py +3 -18
  89. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_jax_flax_integration.py +16 -14
  90. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_jit_script_integration.py +3 -8
  91. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_lazy_loading_integration.py +1 -5
  92. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_models.py +27 -0
  93. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_pytorch_zip_detection.py +1 -1
  94. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_streaming_scan.py +3 -1
  95. modelaudit-0.2.32/tests/test_xdist_status.py +223 -0
  96. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/file/test_filetype.py +70 -0
  97. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/test_result_conversion.py +66 -37
  98. modelaudit-0.2.32/tests/xdist_status.py +204 -0
  99. {modelaudit-0.2.30 → modelaudit-0.2.32}/uv.lock +666 -654
  100. modelaudit-0.2.30/.release-please-manifest.json +0 -3
  101. modelaudit-0.2.30/CLAUDE.md +0 -3
  102. modelaudit-0.2.30/modelaudit/scanners/jax_checkpoint_scanner.py +0 -459
  103. modelaudit-0.2.30/modelaudit/scanners/openvino_scanner.py +0 -135
  104. modelaudit-0.2.30/modelaudit/scanners/tensorrt_scanner.py +0 -73
  105. modelaudit-0.2.30/scripts/benchmark_report.py +0 -195
  106. modelaudit-0.2.30/tests/scanners/test_coreml_scanner.py +0 -282
  107. modelaudit-0.2.30/tests/scanners/test_openvino_scanner.py +0 -61
  108. modelaudit-0.2.30/tests/scanners/test_tensorrt_scanner.py +0 -37
  109. modelaudit-0.2.30/tests/test_benchmark_report.py +0 -113
  110. modelaudit-0.2.30/tests/test_core.py +0 -255
  111. {modelaudit-0.2.30 → modelaudit-0.2.32}/.dockerignore +0 -0
  112. {modelaudit-0.2.30 → modelaudit-0.2.32}/.editorconfig +0 -0
  113. {modelaudit-0.2.30 → modelaudit-0.2.32}/.gitattributes +0 -0
  114. {modelaudit-0.2.30 → modelaudit-0.2.32}/.github/CODEOWNERS +0 -0
  115. {modelaudit-0.2.30 → modelaudit-0.2.32}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  116. {modelaudit-0.2.30 → modelaudit-0.2.32}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  117. {modelaudit-0.2.30 → modelaudit-0.2.32}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  118. {modelaudit-0.2.30 → modelaudit-0.2.32}/.github/markdown-link-check-config.json +0 -0
  119. {modelaudit-0.2.30 → modelaudit-0.2.32}/.github/workflows/codeql.yml +0 -0
  120. {modelaudit-0.2.30 → modelaudit-0.2.32}/.github/workflows/docker-image-test.yml +0 -0
  121. {modelaudit-0.2.30 → modelaudit-0.2.32}/.github/workflows/docker-publish.yml +0 -0
  122. {modelaudit-0.2.30 → modelaudit-0.2.32}/.github/workflows/docs-check.yml +0 -0
  123. {modelaudit-0.2.30 → modelaudit-0.2.32}/.github/workflows/nightly.yml +0 -0
  124. {modelaudit-0.2.30 → modelaudit-0.2.32}/.github/workflows/release-please.yml +0 -0
  125. {modelaudit-0.2.30 → modelaudit-0.2.32}/.github/workflows/test.yml +0 -0
  126. {modelaudit-0.2.30 → modelaudit-0.2.32}/.github/workflows/validate-pr-title.yml +0 -0
  127. {modelaudit-0.2.30 → modelaudit-0.2.32}/.gitignore +0 -0
  128. {modelaudit-0.2.30 → modelaudit-0.2.32}/.mailmap +0 -0
  129. {modelaudit-0.2.30 → modelaudit-0.2.32}/.modelaudit.toml.example +0 -0
  130. {modelaudit-0.2.30 → modelaudit-0.2.32}/.prettierignore +0 -0
  131. {modelaudit-0.2.30 → modelaudit-0.2.32}/CODE_OF_CONDUCT.md +0 -0
  132. {modelaudit-0.2.30 → modelaudit-0.2.32}/CONTRIBUTING.md +0 -0
  133. {modelaudit-0.2.30 → modelaudit-0.2.32}/Dockerfile +0 -0
  134. {modelaudit-0.2.30 → modelaudit-0.2.32}/Dockerfile.full +0 -0
  135. {modelaudit-0.2.30 → modelaudit-0.2.32}/Dockerfile.tensorflow +0 -0
  136. {modelaudit-0.2.30 → modelaudit-0.2.32}/LICENSE +0 -0
  137. {modelaudit-0.2.30 → modelaudit-0.2.32}/MAINTAINERS.md +0 -0
  138. {modelaudit-0.2.30 → modelaudit-0.2.32}/MANIFEST.in +0 -0
  139. {modelaudit-0.2.30 → modelaudit-0.2.32}/README.md +0 -0
  140. {modelaudit-0.2.30 → modelaudit-0.2.32}/RULES.md +0 -0
  141. {modelaudit-0.2.30 → modelaudit-0.2.32}/SECURITY.md +0 -0
  142. {modelaudit-0.2.30 → modelaudit-0.2.32}/SUPPORT.md +0 -0
  143. {modelaudit-0.2.30 → modelaudit-0.2.32}/THIRD_PARTY_NOTICES.md +0 -0
  144. {modelaudit-0.2.30 → modelaudit-0.2.32}/codecov.yml +0 -0
  145. {modelaudit-0.2.30 → modelaudit-0.2.32}/docker-compose.yml +0 -0
  146. {modelaudit-0.2.30 → modelaudit-0.2.32}/docker-entrypoint.sh +0 -0
  147. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/agents/architecture.md +0 -0
  148. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/agents/dependencies.md +0 -0
  149. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/agents/new-scanner-quickstart.md +0 -0
  150. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/agents/release-process.md +0 -0
  151. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/maintainers/cve-gap-pr-plan-2026-03-20.md +0 -0
  152. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/maintainers/cve-process.md +0 -0
  153. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/maintainers/dependency-policy.md +0 -0
  154. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/maintainers/format-gap-plans/coreml-mlmodel.md +0 -0
  155. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/maintainers/format-gap-plans/mxnet-models.md +0 -0
  156. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/maintainers/format-gap-plans/tensorflow-metagraph.md +0 -0
  157. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/maintainers/format-gap-plans/torchserve-mar.md +0 -0
  158. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/maintainers/triage-playbook.md +0 -0
  159. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/security/threat-model.md +0 -0
  160. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/user/compatibility-matrix.md +0 -0
  161. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/user/metadata-extraction.md +0 -0
  162. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/user/offline-air-gapped.md +0 -0
  163. {modelaudit-0.2.30 → modelaudit-0.2.32}/docs/user/security-model.md +0 -0
  164. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/__init__.py +0 -0
  165. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/__main__.py +0 -0
  166. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/analysis/__init__.py +0 -0
  167. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/analysis/anomaly_detector.py +0 -0
  168. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/analysis/enhanced_pattern_detector.py +0 -0
  169. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/analysis/entropy_analyzer.py +0 -0
  170. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/analysis/framework_patterns.py +0 -0
  171. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/analysis/integrated_analyzer.py +0 -0
  172. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/analysis/ml_context_analyzer.py +0 -0
  173. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/analysis/opcode_sequence_analyzer.py +0 -0
  174. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/analysis/semantic_analyzer.py +0 -0
  175. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/analysis/unified_context.py +0 -0
  176. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/auth/__init__.py +0 -0
  177. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/auth/client.py +0 -0
  178. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/auth/config.py +0 -0
  179. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/cache/__init__.py +0 -0
  180. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/cache/adaptive_cache_keys.py +0 -0
  181. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/cache/batch_operations.py +0 -0
  182. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/cache/cache_manager.py +0 -0
  183. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/cache/cache_policy.py +0 -0
  184. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/cache/optimized_config.py +0 -0
  185. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/cache/scan_results_cache.py +0 -0
  186. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/cache/trusted_config_store.py +0 -0
  187. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/config/__init__.py +0 -0
  188. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/config/constants.py +0 -0
  189. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/config/data/spdx_licenses.json +0 -0
  190. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/config/explanations.py +0 -0
  191. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/config/generated_keras_layers.py +0 -0
  192. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/config/local_config.py +0 -0
  193. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/config/name_blacklist.py +0 -0
  194. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/config/rule_config.py +0 -0
  195. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/detectors/__init__.py +0 -0
  196. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/detectors/cve_patterns.py +0 -0
  197. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/detectors/network_comm.py +0 -0
  198. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/detectors/suspicious_symbols.py +0 -0
  199. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/integrations/__init__.py +0 -0
  200. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/integrations/jfrog.py +0 -0
  201. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/integrations/mlflow.py +0 -0
  202. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/integrations/sarif_formatter.py +0 -0
  203. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/integrations/sbom_generator.py +0 -0
  204. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/metadata_extractor.py +0 -0
  205. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/progress/__init__.py +0 -0
  206. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/progress/console.py +0 -0
  207. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/progress/multi_phase.py +0 -0
  208. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/LICENSE +0 -0
  209. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/NOTICE +0 -0
  210. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/__init__.py +0 -0
  211. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/py.typed +0 -0
  212. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/__init__.py +0 -0
  213. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/__init__.py +0 -0
  214. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/__init__.py +0 -0
  215. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/allocation_description_pb2.py +0 -0
  216. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/api_def_pb2.py +0 -0
  217. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/attr_value_pb2.py +0 -0
  218. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/cost_graph_pb2.py +0 -0
  219. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/cpp_shape_inference_pb2.py +0 -0
  220. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/dataset_metadata_pb2.py +0 -0
  221. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/dataset_options_pb2.py +0 -0
  222. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/dataset_pb2.py +0 -0
  223. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/device_attributes_pb2.py +0 -0
  224. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/full_type_pb2.py +0 -0
  225. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/function_pb2.py +0 -0
  226. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/graph_debug_info_pb2.py +0 -0
  227. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/graph_pb2.py +0 -0
  228. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/graph_transfer_info_pb2.py +0 -0
  229. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/kernel_def_pb2.py +0 -0
  230. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/log_memory_pb2.py +0 -0
  231. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/model_pb2.py +0 -0
  232. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/node_def_pb2.py +0 -0
  233. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/op_def_pb2.py +0 -0
  234. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/optimized_function_graph_pb2.py +0 -0
  235. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/reader_base_pb2.py +0 -0
  236. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/resource_handle_pb2.py +0 -0
  237. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/step_stats_pb2.py +0 -0
  238. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/tensor_description_pb2.py +0 -0
  239. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/tensor_pb2.py +0 -0
  240. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/tensor_shape_pb2.py +0 -0
  241. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/tensor_slice_pb2.py +0 -0
  242. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/types_pb2.py +0 -0
  243. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/variable_pb2.py +0 -0
  244. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/versions_pb2.py +0 -0
  245. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/__init__.py +0 -0
  246. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/cluster_pb2.py +0 -0
  247. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/composite_tensor_variant_pb2.py +0 -0
  248. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/control_flow_pb2.py +0 -0
  249. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/core_platform_payloads_pb2.py +0 -0
  250. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/critical_section_pb2.py +0 -0
  251. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/data_service_pb2.py +0 -0
  252. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/debug_event_pb2.py +0 -0
  253. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/debug_pb2.py +0 -0
  254. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/device_filters_pb2.py +0 -0
  255. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/device_properties_pb2.py +0 -0
  256. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/fingerprint_pb2.py +0 -0
  257. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/meta_graph_pb2.py +0 -0
  258. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/named_tensor_pb2.py +0 -0
  259. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/remote_tensor_handle_pb2.py +0 -0
  260. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/rewriter_config_pb2.py +0 -0
  261. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/saved_model_pb2.py +0 -0
  262. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/saved_object_graph_pb2.py +0 -0
  263. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/saver_pb2.py +0 -0
  264. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/service_config_pb2.py +0 -0
  265. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/snapshot_pb2.py +0 -0
  266. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/struct_pb2.py +0 -0
  267. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/tensor_bundle_pb2.py +0 -0
  268. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/trackable_object_graph_pb2.py +0 -0
  269. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/transport_options_pb2.py +0 -0
  270. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/verifier_config_pb2.py +0 -0
  271. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/py.typed +0 -0
  272. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/rules.py +0 -0
  273. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/catboost_scanner.py +0 -0
  274. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/cntk_scanner.py +0 -0
  275. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/executorch_scanner.py +0 -0
  276. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/jinja2_template_scanner.py +0 -0
  277. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/keras_utils.py +0 -0
  278. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/lightgbm_scanner.py +0 -0
  279. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/llamafile_scanner.py +0 -0
  280. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/manifest_scanner.py +0 -0
  281. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/metadata_scanner.py +0 -0
  282. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/mxnet_scanner.py +0 -0
  283. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/numpy_scanner.py +0 -0
  284. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/paddle_scanner.py +0 -0
  285. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/r_serialized_scanner.py +0 -0
  286. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/rknn_scanner.py +0 -0
  287. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/rule_mapper.py +0 -0
  288. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/safetensors_scanner.py +0 -0
  289. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/text_scanner.py +0 -0
  290. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/torch7_scanner.py +0 -0
  291. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/weight_distribution_scanner.py +0 -0
  292. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/scanners/xgboost_scanner.py +0 -0
  293. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/telemetry.py +0 -0
  294. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/__init__.py +0 -0
  295. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/auto_defaults.py +0 -0
  296. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/file/__init__.py +0 -0
  297. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/file/filtering.py +0 -0
  298. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/file/handlers.py +1 -1
  299. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/file/large_file_handler.py +0 -0
  300. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/file/streaming.py +0 -0
  301. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/helpers/__init__.py +0 -0
  302. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/helpers/assets.py +0 -0
  303. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/helpers/auto_defaults.py +0 -0
  304. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/helpers/cache_decorator.py +0 -0
  305. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/helpers/code_validation.py +0 -0
  306. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/helpers/disk_space.py +0 -0
  307. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/helpers/file_hash.py +0 -0
  308. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/helpers/file_iterator.py +0 -0
  309. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/helpers/interrupt_handler.py +0 -0
  310. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/helpers/retry.py +0 -0
  311. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/lfs.py +0 -0
  312. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/model_extensions.py +0 -0
  313. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/sources/__init__.py +0 -0
  314. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/sources/cloud_storage.py +0 -0
  315. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/sources/dvc.py +0 -0
  316. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/sources/huggingface.py +0 -0
  317. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/sources/pytorch_hub.py +0 -0
  318. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/utils/tensorflow_compat.py +0 -0
  319. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/whitelists/__init__.py +0 -0
  320. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/whitelists/huggingface_organizations.py +0 -0
  321. {modelaudit-0.2.30 → modelaudit-0.2.32}/modelaudit/whitelists/huggingface_popular.py +0 -0
  322. {modelaudit-0.2.30 → modelaudit-0.2.32}/package-lock.json +0 -0
  323. {modelaudit-0.2.30 → modelaudit-0.2.32}/package.json +0 -0
  324. {modelaudit-0.2.30 → modelaudit-0.2.32}/pyproject.toml.example +0 -0
  325. {modelaudit-0.2.30 → modelaudit-0.2.32}/release-please-config.json +0 -0
  326. {modelaudit-0.2.30 → modelaudit-0.2.32}/renovate.json +0 -0
  327. {modelaudit-0.2.30 → modelaudit-0.2.32}/scripts/README.md +0 -0
  328. {modelaudit-0.2.30 → modelaudit-0.2.32}/scripts/check_circular_imports.py +0 -0
  329. {modelaudit-0.2.30 → modelaudit-0.2.32}/scripts/compile_tensorflow_protos.sh +0 -0
  330. {modelaudit-0.2.30 → modelaudit-0.2.32}/scripts/fetch_hf_org_models.py +0 -0
  331. {modelaudit-0.2.30 → modelaudit-0.2.32}/scripts/fetch_hf_top_models.py +0 -0
  332. {modelaudit-0.2.30 → modelaudit-0.2.32}/scripts/generate_keras_layer_inventory.py +0 -0
  333. {modelaudit-0.2.30 → modelaudit-0.2.32}/scripts/jax_flax_scanning_demo.py +0 -0
  334. {modelaudit-0.2.30 → modelaudit-0.2.32}/scripts/minimal_circular_check.py +0 -0
  335. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/__init__.py +0 -0
  336. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/analysis/test_analysis_modules.py +0 -0
  337. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/analysis/test_anomaly_detector.py +0 -0
  338. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/analysis/test_enhanced_pattern_detector.py +0 -0
  339. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/analysis/test_framework_patterns.py +0 -0
  340. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/analysis/test_ml_context_analyzer.py +0 -0
  341. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/analysis/test_opcode_sequence_analyzer.py +0 -0
  342. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/analysis/test_unified_context.py +0 -0
  343. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/exploits/exploit1_basic_torch_bypass.pkl +0 -0
  344. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/exploits/exploit2_advanced_torch_bypass.pkl +0 -0
  345. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/exploits/exploit3_sophisticated_hybrid.pkl +0 -0
  346. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/exploits/exploit4_supply_chain_attack.pkl +0 -0
  347. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/exploits/exploit5_ultra_high_confidence.pkl +0 -0
  348. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/exploits/exploit6_ordereddict_bypass.pkl +0 -0
  349. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/exploits/exploit7_nested_collections.pkl +0 -0
  350. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/exploits/exploit9_manual_construction.pkl +0 -0
  351. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/exploits/exploit_ultimate_50pct.pkl +0 -0
  352. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/generators/generate_7z_test_assets.py +0 -0
  353. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/generators/generate_advanced_pickle_tests.py +0 -0
  354. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/generators/generate_evil_pickle.py +0 -0
  355. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/generators/generate_jinja2_test_assets.py +0 -0
  356. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/generators/generate_nested_pickle_assets.py +0 -0
  357. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/generators/generate_os_alias_tests.py +0 -0
  358. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/generators/generate_safe_nested_assets.py +0 -0
  359. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/generators/generate_safetensors_assets.py +0 -0
  360. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/generators/generate_security_assets.py +0 -0
  361. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/pickles/bypass_pocs/gen_bypass_v4.py +0 -0
  362. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/pickles/memo_attack.pkl +0 -0
  363. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/pickles/multiple_stream_attack.pkl +0 -0
  364. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/pickles/nt_alias_attack.pkl +0 -0
  365. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/pickles/posix_alias_attack.pkl +0 -0
  366. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/pickles/stack_global_attack.pkl +0 -0
  367. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/archives/path_traversal.zip +0 -0
  368. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/archives/safe_model.zip +0 -0
  369. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign/chatml_format.json +0 -0
  370. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign/complex_legitimate.json +0 -0
  371. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign/conditional_system.json +0 -0
  372. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign/huggingface_llama.json +0 -0
  373. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign/simple_roles.json +0 -0
  374. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign/special_tokens.json +0 -0
  375. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign_conditional_format.json +0 -0
  376. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign_huggingface_chat.json +0 -0
  377. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign_simple_template.json +0 -0
  378. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign_template.j2 +0 -0
  379. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/edge_cases/empty_template.json +0 -0
  380. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/edge_cases/malformed_template.json +0 -0
  381. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/edge_cases/multiple_templates.json +0 -0
  382. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/edge_cases/no_template.json +0 -0
  383. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/edge_cases/oversized_template.json +0 -0
  384. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/attr_bypass.json +0 -0
  385. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/combined_attack.json +0 -0
  386. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/config_exploit.json +0 -0
  387. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/cve_2024_34359_original.json +0 -0
  388. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/direct_eval.json +0 -0
  389. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/env_extraction.json +0 -0
  390. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/file_access.json +0 -0
  391. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/hex_bypass.json +0 -0
  392. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/loop_discovery.json +0 -0
  393. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/network_exfil.json +0 -0
  394. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/request_exploit.json +0 -0
  395. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/subprocess_injection.json +0 -0
  396. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious_cve_2024_34359.json +0 -0
  397. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious_env_vars.json +0 -0
  398. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious_file_read.json +0 -0
  399. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious_loop_exploit.json +0 -0
  400. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious_obfuscated.json +0 -0
  401. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious_subprocess.template +0 -0
  402. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/obfuscated/base64_payload.json +0 -0
  403. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/obfuscated/char_construction.json +0 -0
  404. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/obfuscated/format_bypass.json +0 -0
  405. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/obfuscated/getattr_bypass.json +0 -0
  406. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/standalone/benign_chat.j2 +0 -0
  407. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/standalone/malicious_standalone.jinja +0 -0
  408. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/standalone/suspicious_benign.template +0 -0
  409. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/tokenizer_config.json +0 -0
  410. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/yaml/malicious_config.yaml +0 -0
  411. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/jinja2/yaml/model_config.yaml +0 -0
  412. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/keras/basic_lambda_layer.h5 +0 -0
  413. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/keras/custom_layer_attack.h5 +0 -0
  414. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/keras/keras_zip_format.keras +0 -0
  415. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/keras/lambda_exfiltration.h5 +0 -0
  416. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/keras/lambda_with_imports.h5 +0 -0
  417. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/keras/loss_injection.h5 +0 -0
  418. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/keras/malicious_lambda.h5 +0 -0
  419. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/keras/metric_injection.h5 +0 -0
  420. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/keras/safe_model.h5 +0 -0
  421. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/manifests/safe_config.json +0 -0
  422. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/manifests/suspicious_config.json +0 -0
  423. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pickles/decode_exec_chain.pkl +0 -0
  424. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pickles/dill_func.pkl +0 -0
  425. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pickles/malicious_model_realistic.pkl +0 -0
  426. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pickles/malicious_system_call.pkl +0 -0
  427. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pickles/nested_pickle_base64.pkl +0 -0
  428. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pickles/nested_pickle_hex.pkl +0 -0
  429. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pickles/nested_pickle_multistage.pkl +0 -0
  430. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pickles/nested_pickle_raw.pkl +0 -0
  431. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pickles/safe_data.pkl +0 -0
  432. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pickles/safe_large_model.pkl +0 -0
  433. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pickles/safe_model_with_binary.pkl +0 -0
  434. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pickles/safe_model_with_encoding.pkl +0 -0
  435. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pickles/safe_model_with_tokens.pkl +0 -0
  436. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pickles/safe_nested_structure.pkl +0 -0
  437. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pickles/simple_nested.pkl +0 -0
  438. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pipeline.skops +0 -0
  439. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pytorch/malicious_eval.pt +0 -0
  440. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/pytorch/safe_model.pt +0 -0
  441. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/safetensors/malicious_import.safetensors +0 -0
  442. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/safetensors/multiple_patterns.safetensors +0 -0
  443. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/safetensors/obfuscated_metadata.safetensors +0 -0
  444. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/safetensors/safe_model.safetensors +0 -0
  445. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/safetensors/script_injection.safetensors +0 -0
  446. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/safetensors/shell_commands.safetensors +0 -0
  447. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/safetensors/suspicious_url.safetensors +0 -0
  448. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/tensorflow/malicious_pyfunc/saved_model.pb +0 -0
  449. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/samples/tensorflow/safe_savedmodel/saved_model.pb +0 -0
  450. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/agpl_component/agpl_model.pkl +0 -0
  451. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/agpl_component/neural_network.py +0 -0
  452. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mit_model/config.json +0 -0
  453. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mit_model/model.py +0 -0
  454. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mit_model/model_weights.pkl +0 -0
  455. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mixed_licenses/LICENSE +0 -0
  456. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mixed_licenses/apache_component.py +0 -0
  457. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mixed_licenses/dataset_cc_nc.json +0 -0
  458. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mixed_licenses/gpl_utility.py +0 -0
  459. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mixed_licenses/mixed_model.pkl +0 -0
  460. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/unlicensed_dataset/embeddings.npy +0 -0
  461. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/unlicensed_dataset/features.csv +0 -0
  462. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/unlicensed_dataset/training_data.json +0 -0
  463. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/scenarios/security_scenarios/mixed_malicious_model/config.json +0 -0
  464. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/assets/scenarios/security_scenarios/mixed_malicious_model/model.pkl +0 -0
  465. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/cache/__init__.py +0 -0
  466. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/cache/test_cache_correctness.py +0 -0
  467. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/cache/test_optimized_config.py +0 -0
  468. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/cli_output.py +0 -0
  469. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/config/__init__.py +0 -0
  470. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/config/test_name_blacklist.py +0 -0
  471. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/demo_license_functionality.py +0 -0
  472. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/detectors/test_builtin_detection.py +0 -0
  473. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/detectors/test_compile_eval_variants.py +0 -0
  474. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/detectors/test_cve_detection.py +0 -0
  475. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/detectors/test_network_comm_detector.py +0 -0
  476. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/detectors/test_runpy_detection.py +0 -0
  477. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/detectors/test_secrets_detector.py +0 -0
  478. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/detectors/test_suspicious_symbols.py +0 -0
  479. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/helpers/__init__.py +0 -0
  480. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/helpers/file_creators.py +0 -0
  481. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/helpers/frameworks.py +0 -0
  482. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/integrations/test_jfrog.py +0 -0
  483. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/integrations/test_jfrog_integration.py +0 -0
  484. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/integrations/test_license_integration.py +0 -0
  485. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/integrations/test_mlflow_integration.py +0 -0
  486. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/integrations/test_sarif_formatter.py +0 -0
  487. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/integrations/test_sbom_license_integration.py +0 -0
  488. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/integrations/test_sbom_url_fixes.py +0 -0
  489. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/progress/__init__.py +0 -0
  490. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/progress/test_base.py +0 -0
  491. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_base_scanner.py +0 -0
  492. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_catboost_scanner.py +0 -0
  493. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_cntk_scanner.py +0 -0
  494. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_executorch_scanner.py +0 -0
  495. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_jinja2_template_scanner.py +0 -0
  496. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_joblib_scanner.py +0 -0
  497. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_lightgbm_scanner.py +0 -0
  498. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_llamafile_scanner.py +0 -0
  499. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_manifest_scanner.py +0 -0
  500. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_metadata_scanner.py +0 -0
  501. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_mxnet_scanner.py +0 -0
  502. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_numpy_scanner.py +0 -0
  503. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_paddle_scanner.py +0 -0
  504. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_r_serialized_scanner.py +0 -0
  505. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_rknn_scanner.py +0 -0
  506. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_rule_code_registry_consistency.py +0 -0
  507. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_rule_mapper.py +0 -0
  508. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_safetensors_scanner.py +0 -0
  509. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_skops_content_analysis.py +0 -0
  510. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_torch7_scanner.py +0 -0
  511. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/scanners/test_weight_distribution_scanner.py +0 -0
  512. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_asset_inventory_integration.py +0 -0
  513. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_asset_list.py +0 -0
  514. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_auth_config.py +0 -0
  515. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_basic.py +0 -0
  516. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_bug1_confidence_exploit.py +0 -0
  517. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_cache_cli.py +0 -0
  518. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_checks_recording.py +0 -0
  519. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_cli.py +0 -0
  520. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_cli_cache_dir.py +0 -0
  521. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_cli_default_command.py +0 -0
  522. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_cli_file_filtering.py +0 -0
  523. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_cli_license_integration.py +0 -0
  524. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_cli_logging_handlers.py +0 -0
  525. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_cli_output.py +0 -0
  526. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_cloud_url_detection.py +0 -0
  527. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_core_asset_extraction.py +0 -0
  528. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_cve_2025_10155_bin_pickle.py +0 -0
  529. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_debug_command.py +0 -0
  530. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_dill_joblib_enhanced.py +0 -0
  531. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_directory_file_filtering.py +0 -0
  532. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_double_interrupt.py +0 -0
  533. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_exit_codes.py +0 -0
  534. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_false_positive_fixes.py +0 -0
  535. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_file_hash.py +0 -0
  536. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_gguf_sbom_integration.py +0 -0
  537. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_graceful_degradation.py +0 -0
  538. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_header_discrepancy.py +0 -0
  539. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_huggingface_extensions.py +0 -0
  540. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_huggingface_symlinks.py +0 -0
  541. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_importlib_detection.py +0 -0
  542. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_lazy_loading.py +0 -0
  543. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_manifest_name_policy.py +0 -0
  544. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_metadata_extractor.py +0 -0
  545. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_nested_pickle_integration.py +0 -0
  546. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_network_comm_integration.py +0 -0
  547. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_os_alias_detection.py +0 -0
  548. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_os_subprocess_detection.py +0 -0
  549. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_path_traversal.py +0 -0
  550. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_performance_benchmarks.py +0 -0
  551. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_pickle_context_filtering.py +0 -0
  552. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_progress.py +0 -0
  553. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_pydantic_models.py +0 -0
  554. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_python_version_warning.py +0 -0
  555. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_real_world_dill_joblib.py +0 -0
  556. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_regression_corpus.py +0 -0
  557. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_regular_scan_hash.py +0 -0
  558. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_rules.py +0 -0
  559. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_safetensors_optimization.py +0 -0
  560. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_secure_hasher.py +0 -0
  561. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_security_asset_integration.py +0 -0
  562. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_security_enhancements.py +0 -0
  563. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_shebang_context.py +0 -0
  564. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_simple_jinja2.py +0 -0
  565. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_sklearn_joblib_false_positive.py +0 -0
  566. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_telemetry.py +0 -0
  567. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_telemetry_decoupling.py +0 -0
  568. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_tensorflow_lambda_detection.py +0 -0
  569. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_timeout_configuration.py +0 -0
  570. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_utils.py +0 -0
  571. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_weak_hash_detection.py +0 -0
  572. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_webbrowser_detection.py +0 -0
  573. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/test_why_explanations.py +0 -0
  574. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/__init__.py +0 -0
  575. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/file/__init__.py +0 -0
  576. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/file/test_advanced_file_handler.py +0 -0
  577. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/file/test_advanced_size_limits.py +0 -0
  578. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/file/test_file_filter.py +0 -0
  579. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/file/test_file_type_validation_integration.py +0 -0
  580. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/file/test_integration_file_type_demo.py +0 -0
  581. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/file/test_large_file_handler.py +0 -0
  582. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/file/test_streaming_analysis.py +0 -0
  583. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/file/test_streaming_preview.py +0 -0
  584. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/helpers/test_asset_from_scan_result.py +0 -0
  585. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/helpers/test_auto_defaults.py +0 -0
  586. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/helpers/test_code_validation.py +0 -0
  587. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/helpers/test_disk_space.py +0 -0
  588. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/helpers/test_file_iterator.py +0 -0
  589. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/helpers/test_interrupt_handling.py +0 -0
  590. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/helpers/test_ml_context_false_positives.py +0 -0
  591. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/helpers/test_py_compile_improvements.py +0 -0
  592. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/helpers/test_secure_hasher.py +0 -0
  593. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/sources/test_cloud_storage.py +0 -0
  594. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/sources/test_dvc_integration.py +0 -0
  595. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/sources/test_huggingface.py +0 -0
  596. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/sources/test_pytorch_hub.py +0 -0
  597. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/utils/test_lfs.py +0 -0
  598. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/whitelists/__init__.py +0 -0
  599. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/whitelists/test_combined.py +0 -0
  600. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/whitelists/test_huggingface_popular.py +0 -0
  601. {modelaudit-0.2.30 → modelaudit-0.2.32}/tests/whitelists/test_organizations.py +0 -0
@@ -12,4 +12,4 @@
12
12
 
13
13
  PRs run a reduced test matrix (Python 3.10 + 3.13). Main branch runs the full matrix (3.10–3.13). Documentation-only changes skip the full test suite.
14
14
 
15
- The performance workflow posts a sticky benchmark summary comment on same-repo PRs and uploads raw benchmark JSON as workflow artifacts.
15
+ The performance workflow posts a sticky benchmark summary comment on same-repo PRs, uploads benchmark JSON plus Markdown summaries as workflow artifacts, and reports regressions or missing benchmarks without blocking the PR.
@@ -4,7 +4,10 @@ on:
4
4
  pull_request:
5
5
  paths:
6
6
  - "modelaudit/**"
7
- - "tests/**"
7
+ - "tests/benchmarks/**"
8
+ - "tests/helpers/**"
9
+ - "tests/conftest.py"
10
+ - "tests/test_benchmark_report.py"
8
11
  - "scripts/benchmark_report.py"
9
12
  - "pyproject.toml"
10
13
  - "uv.lock"
@@ -12,6 +15,16 @@ on:
12
15
  push:
13
16
  branches:
14
17
  - main
18
+ paths:
19
+ - "modelaudit/**"
20
+ - "tests/benchmarks/**"
21
+ - "tests/helpers/**"
22
+ - "tests/conftest.py"
23
+ - "tests/test_benchmark_report.py"
24
+ - "scripts/benchmark_report.py"
25
+ - "pyproject.toml"
26
+ - "uv.lock"
27
+ - ".github/workflows/perf.yml"
15
28
  workflow_dispatch:
16
29
 
17
30
  permissions:
@@ -42,19 +55,32 @@ jobs:
42
55
  run: |
43
56
  uv python pin 3.11
44
57
 
58
+ - name: Prepare benchmark temp directories
59
+ id: paths
60
+ run: |
61
+ artifact_dir="$RUNNER_TEMP/modelaudit-benchmarks"
62
+ base_worktree="$RUNNER_TEMP/modelaudit-base"
63
+ echo "BENCHMARK_ARTIFACT_DIR=$artifact_dir" >> "$GITHUB_ENV"
64
+ echo "BENCHMARK_BASE_WORKTREE=$base_worktree" >> "$GITHUB_ENV"
65
+ echo "artifact_dir=$artifact_dir" >> "$GITHUB_OUTPUT"
66
+ echo "base_worktree=$base_worktree" >> "$GITHUB_OUTPUT"
67
+ rm -rf "$artifact_dir" "$base_worktree"
68
+ mkdir -p "$artifact_dir"
69
+
45
70
  - name: Benchmark base commit
46
71
  if: github.event_name == 'pull_request'
72
+ env:
73
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
47
74
  run: |
48
- git worktree add /tmp/modelaudit-base "${{ github.event.pull_request.base.sha }}"
49
- cd /tmp/modelaudit-base
50
- if [ ! -f tests/benchmarks/test_scan_benchmarks.py ]; then
75
+ set -euo pipefail
76
+ git worktree add --detach "$BENCHMARK_BASE_WORKTREE" "$BASE_SHA"
77
+ if [ ! -f "$BENCHMARK_BASE_WORKTREE/tests/benchmarks/test_scan_benchmarks.py" ]; then
51
78
  echo "Base branch does not include the benchmark suite yet; skipping baseline run."
52
79
  exit 0
53
80
  fi
54
- uv python pin 3.11
55
- uv run --locked --with pytest-benchmark pytest \
81
+ uv run --directory "$BENCHMARK_BASE_WORKTREE" --python 3.11 --locked --with pytest-benchmark pytest \
56
82
  tests/benchmarks/test_scan_benchmarks.py \
57
- --benchmark-json=/tmp/benchmark-base.json \
83
+ --benchmark-json="$BENCHMARK_ARTIFACT_DIR/benchmark-base.json" \
58
84
  -q
59
85
 
60
86
  - name: Benchmark current commit
@@ -62,43 +88,51 @@ jobs:
62
88
  # Keep this lane single-process; pytest-benchmark disables itself under xdist.
63
89
  uv run --locked --with pytest-benchmark pytest \
64
90
  tests/benchmarks/test_scan_benchmarks.py \
65
- --benchmark-json=/tmp/benchmark-head.json \
91
+ --benchmark-json="$BENCHMARK_ARTIFACT_DIR/benchmark-head.json" \
66
92
  -q
67
93
 
68
94
  - name: Compare against base
69
95
  id: compare
70
96
  if: github.event_name == 'pull_request'
71
- continue-on-error: true
72
97
  run: |
73
- if [ -f /tmp/benchmark-base.json ]; then
74
- set +e
98
+ {
99
+ echo "[Workflow run and artifacts](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID})"
100
+ echo
101
+ } > "$BENCHMARK_ARTIFACT_DIR/benchmark-comment.md"
102
+ if [ -f "$BENCHMARK_ARTIFACT_DIR/benchmark-base.json" ]; then
75
103
  uv run --locked python scripts/benchmark_report.py \
76
- --current /tmp/benchmark-head.json \
77
- --baseline /tmp/benchmark-base.json \
104
+ --current "$BENCHMARK_ARTIFACT_DIR/benchmark-head.json" \
105
+ --baseline "$BENCHMARK_ARTIFACT_DIR/benchmark-base.json" \
78
106
  --threshold 0.15 \
79
- --summary-file /tmp/benchmark-comment.md
80
- compare_exit=$?
81
- set -e
107
+ --summary-file "$BENCHMARK_ARTIFACT_DIR/benchmark-compare.md"
82
108
  else
83
109
  {
84
110
  echo "Base branch does not include the benchmark suite yet; showing current results only."
85
111
  echo
86
- } > /tmp/benchmark-comment.md
112
+ } > "$BENCHMARK_ARTIFACT_DIR/benchmark-current.md"
87
113
  uv run --locked python scripts/benchmark_report.py \
88
- --current /tmp/benchmark-head.json \
89
- --summary-file /tmp/benchmark-current.md
90
- cat /tmp/benchmark-current.md >> /tmp/benchmark-comment.md
91
- compare_exit=0
114
+ --current "$BENCHMARK_ARTIFACT_DIR/benchmark-head.json" \
115
+ --summary-file "$BENCHMARK_ARTIFACT_DIR/benchmark-current-report.md"
116
+ cat "$BENCHMARK_ARTIFACT_DIR/benchmark-current.md" >> "$BENCHMARK_ARTIFACT_DIR/benchmark-comment.md"
117
+ cat "$BENCHMARK_ARTIFACT_DIR/benchmark-current-report.md" >> "$BENCHMARK_ARTIFACT_DIR/benchmark-comment.md"
118
+ fi
119
+ if [ -f "$BENCHMARK_ARTIFACT_DIR/benchmark-compare.md" ]; then
120
+ cat "$BENCHMARK_ARTIFACT_DIR/benchmark-compare.md" >> "$BENCHMARK_ARTIFACT_DIR/benchmark-comment.md"
92
121
  fi
93
- cat /tmp/benchmark-comment.md >> "$GITHUB_STEP_SUMMARY"
94
- exit "$compare_exit"
122
+ cat "$BENCHMARK_ARTIFACT_DIR/benchmark-comment.md" >> "$GITHUB_STEP_SUMMARY"
95
123
 
96
124
  - name: Summarize current results
97
125
  if: github.event_name != 'pull_request'
98
126
  run: |
127
+ {
128
+ echo "[Workflow run and artifacts](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID})"
129
+ echo
130
+ } > "$BENCHMARK_ARTIFACT_DIR/benchmark-summary.md"
99
131
  uv run --locked python scripts/benchmark_report.py \
100
- --current /tmp/benchmark-head.json \
101
- --summary-file "$GITHUB_STEP_SUMMARY"
132
+ --current "$BENCHMARK_ARTIFACT_DIR/benchmark-head.json" \
133
+ --summary-file "$BENCHMARK_ARTIFACT_DIR/benchmark-current.md"
134
+ cat "$BENCHMARK_ARTIFACT_DIR/benchmark-current.md" >> "$BENCHMARK_ARTIFACT_DIR/benchmark-summary.md"
135
+ cat "$BENCHMARK_ARTIFACT_DIR/benchmark-summary.md" >> "$GITHUB_STEP_SUMMARY"
102
136
 
103
137
  - name: Comment benchmark summary on PR
104
138
  if: >
@@ -107,7 +141,7 @@ jobs:
107
141
  github.event.pull_request.head.repo.full_name == github.repository
108
142
  uses: actions/github-script@v8
109
143
  env:
110
- COMMENT_BODY_PATH: /tmp/benchmark-comment.md
144
+ COMMENT_BODY_PATH: ${{ steps.paths.outputs.artifact_dir }}/benchmark-comment.md
111
145
  with:
112
146
  script: |
113
147
  const fs = require("fs")
@@ -149,15 +183,14 @@ jobs:
149
183
 
150
184
  - name: Upload benchmark artifacts
151
185
  if: always()
152
- uses: actions/upload-artifact@v4
186
+ uses: actions/upload-artifact@v7
153
187
  with:
154
188
  name: benchmark-results-python-3.11
155
- path: |
156
- /tmp/benchmark-head.json
157
- /tmp/benchmark-base.json
189
+ path: ${{ steps.paths.outputs.artifact_dir }}
158
190
  if-no-files-found: error
159
191
  retention-days: 14
160
192
 
161
- - name: Fail on benchmark regression
162
- if: github.event_name == 'pull_request' && steps.compare.outcome == 'failure'
163
- run: exit 1
193
+ - name: Cleanup benchmark base worktree
194
+ if: always() && github.event_name == 'pull_request'
195
+ run: |
196
+ git worktree remove --force "$BENCHMARK_BASE_WORKTREE" || true
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.2.32"
3
+ }
@@ -55,9 +55,7 @@ git checkout -b feat/your-feature-name # or fix/, chore/, test/
55
55
  # Commit (conventional)
56
56
  git commit -m "feat: add scanner for XYZ format
57
57
 
58
- Description here.
59
-
60
- Co-Authored-By: Claude <noreply@anthropic.com>"
58
+ Description here."
61
59
 
62
60
  # PR (after validation) - ALL changes go through PRs
63
61
  git push -u origin feat/your-feature-name
@@ -130,7 +128,7 @@ When adding CVE detections to existing scanners, follow these rules distilled fr
130
128
  - **Doc/comment guards:** Use majority-line analysis (>50% doc lines via `_is_primarily_documentation()`), not substring checks — `"#" in content` is trivially bypassable by embedding a comment token in a payload.
131
129
  - **`STACK_GLOBAL` handling:** These opcodes have `arg=None` in pickletools; reconstruct `module.class` by walking backwards to find preceding `SHORT_BINUNICODE`/`BINUNICODE` ops.
132
130
  - **Dict short-circuit scope:** Track which op produces the `SETITEM` target — an unrelated `EMPTY_DICT` in the lookback window must not suppress detection of a `SETITEM` targeting a `REDUCE`/`NEWOBJ` result.
133
- - **Version comparison:** Handle PEP 440 prerelease tags (`a`, `b`, `rc`, `dev`) — `2.10.0a0` is still vulnerable, not the fix.
131
+ - **Version comparison:** Handle PEP 440 prerelease tags (`a`, `b`, `rc`, `dev`) — for a framework/library version gate, a prerelease like `2.10.0a0` is still vulnerable, not the fix.
134
132
  - **Bounded reads:** Cap archive member reads for metadata validation (10 MB) to prevent memory spikes on large pickles.
135
133
  - **Pattern registration:** New CVE pattern lists must be added to `validate_patterns()` in `suspicious_symbols.py`.
136
134
 
@@ -5,6 +5,64 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.32](https://github.com/promptfoo/modelaudit/compare/v0.2.31...v0.2.32) (2026-04-05)
9
+
10
+ ### Bug Fixes
11
+
12
+ - detect punctuated TensorRT tmp paths ([#867](https://github.com/promptfoo/modelaudit/issues/867)) ([9607530](https://github.com/promptfoo/modelaudit/commit/96075302de2d71b228be97e49698d6a1ad6b35bf))
13
+ - fail closed on OpenVINO DOCTYPE parse errors ([#864](https://github.com/promptfoo/modelaudit/issues/864)) ([f5b19c4](https://github.com/promptfoo/modelaudit/commit/f5b19c48c7eab876e29f1f474c555b902fa9b6ce))
14
+ - ignore OCI metadata URLs during layer discovery ([#866](https://github.com/promptfoo/modelaudit/issues/866)) ([0b24e3f](https://github.com/promptfoo/modelaudit/commit/0b24e3f7a0e013541bce100b64f1d69558bd807d))
15
+ - reduce PMML subprocess extension false positives ([#869](https://github.com/promptfoo/modelaudit/issues/869)) ([5e6f79d](https://github.com/promptfoo/modelaudit/commit/5e6f79dc134267202b5a4b841a8946af865ebd15))
16
+ - tolerate bounded CoreML custom block truncation ([#868](https://github.com/promptfoo/modelaudit/issues/868)) ([34df06d](https://github.com/promptfoo/modelaudit/commit/34df06dd2c12b69815a2a15f1273085856bebf64))
17
+
18
+ ## [Unreleased]
19
+
20
+ ### Bug Fixes
21
+
22
+ - avoid CoreML nested parse failures on bounded-read truncation
23
+ - detect punctuation-delimited TensorRT `/tmp` plugin paths
24
+ - avoid PMML `<Extension>` false positives for benign `subprocess` prose while preserving `subprocess.getoutput()`, `subprocess.getstatusoutput()`, and `importlib.import_module("subprocess")` detections
25
+
26
+ ## [0.2.31](https://github.com/promptfoo/modelaudit/compare/v0.2.30...v0.2.31) (2026-04-04)
27
+
28
+ ### Bug Fixes
29
+
30
+ - clean up CodeQL quality findings ([#862](https://github.com/promptfoo/modelaudit/issues/862)) ([5fbcb10](https://github.com/promptfoo/modelaudit/commit/5fbcb101322791831fbf6159bab454231a7f01f0))
31
+ - detect long-gap protocol-0 pickle tails ([#844](https://github.com/promptfoo/modelaudit/issues/844)) ([cbc24b2](https://github.com/promptfoo/modelaudit/commit/cbc24b2af187055622b3776b3e49cca0c43ce9b7))
32
+ - detect protocol 0/1 pickles with trailing junk ([#827](https://github.com/promptfoo/modelaudit/issues/827)) ([d07869d](https://github.com/promptfoo/modelaudit/commit/d07869dadc80de567db894dd8ceda9de53038a71))
33
+ - fail closed on conflicting Keras ZIP config aliases ([#847](https://github.com/promptfoo/modelaudit/issues/847)) ([ab426b8](https://github.com/promptfoo/modelaudit/commit/ab426b8230b1766b4a7678803c90c45256bcdf54))
34
+ - harden content-routed .keras ZIP recursive scans ([#828](https://github.com/promptfoo/modelaudit/issues/828)) ([a607df7](https://github.com/promptfoo/modelaudit/commit/a607df7e8f94623c7802ef3af90896e1b4c564cc))
35
+ - harden CoreML scanner ([#859](https://github.com/promptfoo/modelaudit/issues/859)) ([50da953](https://github.com/promptfoo/modelaudit/commit/50da95393c6b0be318cb33535e12d16a361663ac))
36
+ - harden Flax msgpack stream scanning ([#842](https://github.com/promptfoo/modelaudit/issues/842)) ([34e4595](https://github.com/promptfoo/modelaudit/commit/34e4595b2017f272c951a45c6f89a0fa8997f8d5))
37
+ - harden JAX checkpoint scanner heuristics ([#837](https://github.com/promptfoo/modelaudit/issues/837)) ([1042c20](https://github.com/promptfoo/modelaudit/commit/1042c20c48ce09613125967623c715babc7b9da8))
38
+ - harden Joblib raw/compressed pickle analysis ([#841](https://github.com/promptfoo/modelaudit/issues/841)) ([9d16470](https://github.com/promptfoo/modelaudit/commit/9d164701345aebef8ad03421ac66cbcca6c61aed))
39
+ - harden Keras H5 scanner ([#848](https://github.com/promptfoo/modelaudit/issues/848)) ([aa0ef28](https://github.com/promptfoo/modelaudit/commit/aa0ef2878593e639a5b868a4be2d5de7a6c9c23b))
40
+ - harden MAR duplicate-member analysis ([#830](https://github.com/promptfoo/modelaudit/issues/830)) ([8d4e056](https://github.com/promptfoo/modelaudit/commit/8d4e0567f1df15405f429cefe3cd894aada3b712))
41
+ - harden NeMo target checks and YAML bounds ([#839](https://github.com/promptfoo/modelaudit/issues/839)) ([63ff67d](https://github.com/promptfoo/modelaudit/commit/63ff67d45aa7d454e63781c71039839c35e74892))
42
+ - harden OCI layer scanner ([#856](https://github.com/promptfoo/modelaudit/issues/856)) ([637a4da](https://github.com/promptfoo/modelaudit/commit/637a4daa72047c15598660320f2f12de6a43e627))
43
+ - harden ONNX scanner ([#857](https://github.com/promptfoo/modelaudit/issues/857)) ([de304a7](https://github.com/promptfoo/modelaudit/commit/de304a77513abf551e96a1828f57fdfdd11150c2))
44
+ - harden OpenVINO scanner ([#852](https://github.com/promptfoo/modelaudit/issues/852)) ([a97b76e](https://github.com/promptfoo/modelaudit/commit/a97b76efc44940d70b6cc0f485485d5c5ff7b550))
45
+ - harden PMML scanner ([#860](https://github.com/promptfoo/modelaudit/issues/860)) ([cbcd88a](https://github.com/promptfoo/modelaudit/commit/cbcd88a91cc8b3f9986554b255be366fcae672a8))
46
+ - harden post-budget pickle tail scan bounds ([16d6db3](https://github.com/promptfoo/modelaudit/commit/16d6db39a6263bc923415d34f7501765550e3564))
47
+ - harden PyTorch binary chunk scanning ([#846](https://github.com/promptfoo/modelaudit/issues/846)) ([930c0bf](https://github.com/promptfoo/modelaudit/commit/930c0bf32b53fbc32252c1b2d98aa1f30716eece))
48
+ - harden SevenZip scanner ([#855](https://github.com/promptfoo/modelaudit/issues/855)) ([8d0c362](https://github.com/promptfoo/modelaudit/commit/8d0c362770f4261eefd7461309e7de09b923587d))
49
+ - harden skops archive routing, recursion, and scanner reporting ([#829](https://github.com/promptfoo/modelaudit/issues/829)) ([fb13f68](https://github.com/promptfoo/modelaudit/commit/fb13f6880fdf80e2e78f5f3f30d9b31c2cff17a3))
50
+ - harden Skops CVE status and card fallback detection ([#843](https://github.com/promptfoo/modelaudit/issues/843)) ([9dd964f](https://github.com/promptfoo/modelaudit/commit/9dd964f0aff86092178578f5b952418a6ec52200))
51
+ - harden TAR scanner ([#854](https://github.com/promptfoo/modelaudit/issues/854)) ([219ce54](https://github.com/promptfoo/modelaudit/commit/219ce54446385e87739beacb2b9a8629cde31abb))
52
+ - harden TensorFlow MetaGraph scanner ([#850](https://github.com/promptfoo/modelaudit/issues/850)) ([2dacc9d](https://github.com/promptfoo/modelaudit/commit/2dacc9dcf844ff8ecd335ad1604519b07fc95432))
53
+ - harden TensorFlow SavedModel scanner ([#849](https://github.com/promptfoo/modelaudit/issues/849)) ([f42b7f2](https://github.com/promptfoo/modelaudit/commit/f42b7f2aa560ff72f495a330870478f9028d4fc3))
54
+ - harden TensorRT scanner ([#858](https://github.com/promptfoo/modelaudit/issues/858)) ([c923b55](https://github.com/promptfoo/modelaudit/commit/c923b55df6e8101f40728cbad254d708eea515c5))
55
+ - harden TFLite scanner ([#851](https://github.com/promptfoo/modelaudit/issues/851)) ([b1b1060](https://github.com/promptfoo/modelaudit/commit/b1b1060ae746047becec36356c6a3d3c8227c723))
56
+ - harden TorchServe MAR handler and manifest analysis ([#840](https://github.com/promptfoo/modelaudit/issues/840)) ([6fc0437](https://github.com/promptfoo/modelaudit/commit/6fc04375fd4709869766418e1873231623458e59))
57
+ - harden ZIP scanner ([#853](https://github.com/promptfoo/modelaudit/issues/853)) ([4ccec1a](https://github.com/promptfoo/modelaudit/commit/4ccec1afcd66b2bac3c75f6bd635f34b446090ea))
58
+ - reject raw trailers in zlib wrappers ([#838](https://github.com/promptfoo/modelaudit/issues/838)) ([3b15e2e](https://github.com/promptfoo/modelaudit/commit/3b15e2e1d148d1c700c6d5300655b5e4bb388d70))
59
+ - scan duplicate PyTorch ZIP members ([#845](https://github.com/promptfoo/modelaudit/issues/845)) ([4f63b22](https://github.com/promptfoo/modelaudit/commit/4f63b2277b8d843411d833d00bcf33615b8fb17b))
60
+
61
+ ### Documentation
62
+
63
+ - remove Claude-specific commit trailer ([#834](https://github.com/promptfoo/modelaudit/issues/834)) ([d891025](https://github.com/promptfoo/modelaudit/commit/d891025791128245f293057f4849b481806292c7))
64
+ - simplify CLAUDE shim ([#835](https://github.com/promptfoo/modelaudit/issues/835)) ([616ee31](https://github.com/promptfoo/modelaudit/commit/616ee318019e188f90ee1d41b2a2aaaee9c9444e))
65
+
8
66
  ## [0.2.30](https://github.com/promptfoo/modelaudit/compare/v0.2.29...v0.2.30) (2026-03-30)
9
67
 
10
68
  ### Bug Fixes
@@ -107,10 +165,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
107
165
 
108
166
  ### Fixed
109
167
 
168
+ - **security:** route renamed TFLite FlatBuffers by magic bytes, enforce scanner file-size limits before model reads, and fail closed instead of propagating malformed structure traversal exceptions
169
+ - **onnx:** fail closed on CRITICAL findings, detect `PyFunc` operators and Windows absolute external-data paths, validate external tensor slices with the current ONNX dtype API, and avoid Python-op substring false positives
170
+ - **tensorrt:** route `.trt` engines, detect case-variant and UTF-16 suspicious strings, and avoid substring false positives in benign engine metadata
171
+ - **coreml:** detect Python 3 command metadata, Windows and bundle-macro linked-model escapes, malformed custom-code protobuf blocks, and custom layers nested under pipeline wrappers while preserving safe-key metadata URL inspection
172
+ - **pmml:** enforce max-file-size limits, inspect namespaced Extension/script tags, ignore DOCTYPE/ENTITY text inside XML comments/CDATA, avoid recursive text-walk crashes on deeply nested Extension trees, and fail closed when CRITICAL PMML findings are present
173
+ - **gguf:** fall back to the GGUF spec default tensor-data alignment after rejecting invalid `general.alignment` metadata values
174
+ - **security:** detect protocol 0/1 pickle streams hidden behind long separator gaps after an initial safe pickle stream
175
+ - **security:** preserve failed status for malicious Skops CVE detections and avoid CVE-2025-54886 false positives on benign README/model-card text such as "download"
176
+ - **security:** enforce Flax msgpack scanner file-size limits before full reads, scan trailing msgpack stream objects with a bounded object-count cap, downgrade benign container-like trailing-object findings to INFO, and preserve failed status when CRITICAL findings are reported
177
+ - **security:** route `.joblib` files through the Joblib scanner, scan raw protocol-0/1 payloads directly, support gzip/bzip2/lzma/zlib wrappers with bounded output and trailing-data checks, preserve embedded Pickle finding locations, and fail closed on undecodable/trailing-wrapper errors
178
+ - **security:** detect direct `getattr(module, "dangerous")` handler calls in TorchServe MAR archives, parse conflicting duplicate manifests without silently downgrading hidden handlers, and suppress collision warnings for byte-identical duplicate manifests
179
+ - **security:** reduce NeMo Hydra `_target_` false positives by matching suspicious identifiers on token boundaries, preserve CVE-2025-23304 details on suspicious-target findings, and reject oversized YAML members before parsing
180
+ - **security:** detect protocol 0/1 pickle streams with trivial opcode prefixes even when `STOP` is followed by trailing junk, while preserving plain-text near-match rejection
181
+ - **security:** detect protocol 0/1 pickle streams whose dangerous opcode appears after large trivial padding or after a non-trivial probe-boundary prelude, reject all-trivial no-`STOP` probe prefixes, and preserve rule codes across cached scan-result round trips
182
+ - **license:** bound binary header scans and reuse compiled patterns to avoid full-file regex passes on large model archives
110
183
  - **security:** stop iterating malformed TFLite models after excessive subgraph counts are detected
184
+ - **openvino:** route forbidden-DOCTYPE IR XML into the OpenVINO scanner, fail closed on XML parse errors, and suppress warning-level format-validation noise for benign `.xml` models with no distinctive magic bytes
185
+ - **security:** fail closed on conflicting duplicate or alias Keras root members so benign trailing `config.json` entries cannot hide malicious earlier configs, while accepting byte-identical duplicates without warning noise
186
+ - **security:** detect PyTorch binary code and blacklist patterns that straddle chunk boundaries, avoid duplicate overlap reports, and return `success=False` when CRITICAL findings are present
187
+ - **security:** scan every duplicate PyTorch ZIP member by physical archive entry and report conflicting duplicate names at INFO severity so benign trailing `data.pkl` entries cannot shadow malicious earlier payloads without making benign-but-conflicting duplicates warning-fail by themselves
188
+ - **security:** route misnamed Skops ZIPs by bounded schema sniffing, treat encrypted Skops-like schema members as non-matches instead of crashing routing, recurse into embedded members while preserving Skops-specific CVE checks, avoid tiny nested `.bin` false positives on clean archive members, preserve nested-member byte accounting, and preserve CLI `scanner_names` in aggregated JSON output
189
+ - **pickle:** bound post-budget global fallback state, retained findings, and deadline checks to prevent crafted pickle tails from exhausting scanner memory or flooding logs
111
190
  - **pickle:** mark timeout-, budget-, recursion-, and resource-limited pickle scans as inconclusive so clean-looking partial analysis returns exit code 2 unless real security findings were reported
112
191
  - route misnamed ZIP, HDF5, and 7z files through content-aware scanner selection
192
+ - **security:** recursively scan all members of content-routed `.keras` ZIP archives with bounded per-member extraction, prefer canonical root members over normalized aliases, and fail closed on ambiguous duplicate aliases so embedded payloads and `./config.json` entries are not skipped
193
+ - **security:** scan duplicate ZIP entries by physical archive member instead of resolving repeated names to the final entry, preventing shadowed payloads from being skipped during recursive archive analysis
194
+ - bound Keras `config.json` and `metadata.json` member reads before JSON parsing
195
+ - **openvino:** parse XML roots for long-prolog routing, enforce size limits before parsing, scan nested layer attributes for external library references, and avoid importlib substring false positives
196
+ - **zip:** propagate nested critical findings and incomplete archive traversal to `success=False`, and bound symlink-target reads before path validation
197
+ - **tar:** propagate nested critical findings and partial archive traversal to `success=False`, continue after per-entry extraction errors, and normalize malformed archive-limit configs to safe defaults
198
+ - route oversized config-only Keras ZIP archives by bounded config-prefix sniffing instead of falling back to the generic ZIP scanner
113
199
  - preserve disguised model files during directory prefiltering without promoting document ZIPs
200
+ - fail closed on duplicate 7z entries, nested critical findings, probe-limit truncation, and malformed 7z safety-limit configs
201
+ - **oci:** fail closed on nested findings and partial layer traversal, content-sniff misnamed layer members, normalize cosmetic layer-ref suffix changes, and reject oversized members before temp extraction
202
+ - **oci:** ignore non-layer metadata strings ending in `.tar.gz` when collecting manifest layer refs so benign URLs do not become false missing-layer failures
114
203
  - recurse into nested 7z members even when their filenames use misleading extensions
115
204
  - fail closed on extreme-size files when a scanner lacks bounded large-file analysis
116
205
  - harden scan-cache invalidation and skip caching operational scan failures
@@ -118,11 +207,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
118
207
  - avoid materializing streaming directory iterators in memory
119
208
  - fail closed when JFrog folder downloads return only partial results
120
209
  - **keras:** anchor safe Lambda normalization regexes in H5 scanning so appended statements (for example `; __import__(...)`) cannot bypass dangerous-code analysis
210
+ - **keras:** harden Keras H5 scanning by propagating CRITICAL findings to `success=False`, scanning wrapper-owned nested layers, parsing prerelease fix-boundary versions correctly, and matching suspicious module/config tokens without benign substring false positives
121
211
  - complete primary header-format routing in `core.py` so all registered model formats map to scanner IDs (including OpenVINO/PMML/CNTK/LightGBM/Torch7/CatBoost/RKNN/MXNet/NeMo/Llamafile/TFLite/CoreML/Paddle/TensorRT/Flax/R/ExecuTorch/7z/compressed/skops/joblib/xgboost/jax_checkpoint), add `.skops` extension detection coverage without spurious ZIP mismatch noise, and route ZIP-backed PyTorch `.ckpt`/`.pkl` containers through the PyTorch ZIP path
122
212
  - **security:** track pickle `BUILD`-driven `__setstate__` mutation on non-safe globals and block tree-model opcode-threshold escalation when dangerous globals are present in-stream
123
213
  - **safetensors:** include BOOL, BF16, F8_E4M3, and F8_E5M2 dtypes in tensor-size validation so malformed offsets are no longer skipped
124
214
  - harden pickle symbolic stack simulation by ignoring stack-neutral opcodes and using unknown sentinels for unhandled stack pushes
125
215
  - **security:** scan TensorFlow SavedModel `assets/` and `assets.extra/` directories for executable-like content (shebang scripts, ELF/Mach-O binaries, pickle magic, and embedded Python source patterns)
216
+ - **security:** make TensorFlow SavedModel scans fail closed on CRITICAL findings, avoid substring false positives in PyFunc function references, and treat `blacklist_patterns=None` as disabled instead of emitting DEBUG read errors
126
217
  - **security:** enforce SafeTensors `MAX_HEADER_BYTES` during `scan()` and skip regex-heavy metadata-content analysis when headers exceed the configured limit to reduce header-based DoS risk
127
218
  - emit a one-time warning when the HuggingFace whitelist snapshot is older than 90 days while preserving existing whitelist severity downgrades
128
219
  - treat pickle scan timeouts as unsuccessful while preserving post-budget tail scans after opcode truncation
@@ -173,6 +264,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
173
264
  - **security:** harden TensorFlow weight extraction limits to bound actual tensor payload materialization, including malformed `tensor_content` and string-backed tensors, and continue scanning past oversized `Const` nodes
174
265
  - **security:** stream TAR members to temp files under size limits instead of buffering whole entries in memory during scan
175
266
  - **security:** inspect TensorFlow SavedModel function definitions when scanning for dangerous ops and protobuf string abuse, with function-aware finding locations
267
+ - **security:** route oversized TensorFlow MetaGraph files to fail-closed parse-budget scans, inspect `AttrValue.func.name` references in executable ops, and restore oversized-attribute anomaly detection after bounded string decoding
176
268
  - **cli:** include streamed artifacts as SBOM components when `scan --stream --sbom` is used
177
269
  - **cli:** exclude HuggingFace download cache bookkeeping files from remote SBOMs and asset lists
178
270
  - **cli:** add `--no-whitelist` and `--strict` whitelist/caching hardening so CI scans can disable HF severity downgrades and force uncached analysis
@@ -0,0 +1 @@
1
+ @AGENTS.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modelaudit
3
- Version: 0.2.30
3
+ Version: 0.2.32
4
4
  Summary: Static scanning library for detecting malicious code, backdoors, and other security risks in ML model files
5
5
  Project-URL: Repository, https://github.com/promptfoo/modelaudit
6
6
  Project-URL: Homepage, https://github.com/promptfoo/modelaudit
@@ -297,13 +297,11 @@ class DefaultCommandGroup(click.Group):
297
297
  @click.version_option(__version__)
298
298
  def cli() -> None:
299
299
  """Static scanner for ML models"""
300
- pass
301
300
 
302
301
 
303
302
  @cli.group()
304
303
  def auth() -> None:
305
304
  """Manage authentication"""
306
- pass
307
305
 
308
306
 
309
307
  @auth.command()
@@ -430,7 +428,6 @@ def whoami() -> None:
430
428
  @cli.group()
431
429
  def cache() -> None:
432
430
  """Manage scan results cache"""
433
- pass
434
431
 
435
432
 
436
433
  @cache.command()
@@ -26,6 +26,7 @@ from modelaudit.utils.file.detection import (
26
26
  is_executorch_archive,
27
27
  is_keras_zip_archive,
28
28
  is_pytorch_zip_archive,
29
+ is_skops_archive,
29
30
  is_torchserve_mar_archive,
30
31
  validate_file_type,
31
32
  )
@@ -261,8 +262,12 @@ def _select_preferred_scanner_id(path: str, header_format: str, ext: str) -> str
261
262
  return "pytorch_zip"
262
263
  if is_executorch_archive(path):
263
264
  return "executorch"
265
+ if is_skops_archive(path):
266
+ return "skops"
264
267
  if ext == ".skops":
265
268
  return "skops"
269
+ if ext == ".joblib":
270
+ return "joblib"
266
271
 
267
272
  if ext == ".bin":
268
273
  # ZIP-backed torch.save() .bin files are routed through the pickle scanner,
@@ -273,6 +278,12 @@ def _select_preferred_scanner_id(path: str, header_format: str, ext: str) -> str
273
278
  if header_format == "hdf5":
274
279
  return "keras_h5"
275
280
 
281
+ if ext == ".joblib" and header_format in {"compressed", "pickle"}:
282
+ return "joblib"
283
+
284
+ if header_format == "tar" and ext == ".nemo":
285
+ return "nemo"
286
+
276
287
  return HEADER_FORMAT_TO_SCANNER_ID.get(header_format)
277
288
 
278
289
 
@@ -507,9 +518,15 @@ def _group_checks_by_asset(checks_list: list[Any]) -> dict[tuple[str, str], list
507
518
  location = check.get("location", "")
508
519
  primary_asset = _extract_primary_asset_from_location(location)
509
520
  details = check.get("details")
521
+ zip_entry_id = details.get("zip_entry_id") if isinstance(details, dict) else None
510
522
  zip_entry = details.get("zip_entry") if isinstance(details, dict) else None
511
523
 
512
- asset_group = f"{primary_asset}:{zip_entry}" if isinstance(zip_entry, str) and zip_entry else primary_asset
524
+ if isinstance(zip_entry_id, str) and zip_entry_id:
525
+ asset_group = f"{primary_asset}:{zip_entry_id}"
526
+ elif isinstance(zip_entry, str) and zip_entry:
527
+ asset_group = f"{primary_asset}:{zip_entry}"
528
+ else:
529
+ asset_group = primary_asset
513
530
 
514
531
  group_key = (check_name, asset_group)
515
532
  check_groups[group_key].append(check)
@@ -1126,9 +1143,6 @@ def scan_model_directory_or_file(
1126
1143
  )
1127
1144
  _add_error_asset_to_results(results, file_path)
1128
1145
 
1129
- # This section is now handled by the content grouping logic above
1130
- pass
1131
-
1132
1146
  # Final progress update for directory scan
1133
1147
  if progress_callback and not limit_reached and total_files is not None and total_files > 0:
1134
1148
  progress_callback(
@@ -366,7 +366,11 @@ class JITScriptDetector:
366
366
  )
367
367
 
368
368
  # Check for Python operators (ONNX-Script)
369
- if b"PythonOp" in data or b"PyOp" in data:
369
+ python_op_pattern = re.compile(
370
+ rb"(?<![A-Za-z0-9_])(?:PyFunc(?:Stateless)?|EagerPyFunc|PythonOp|PyOp)(?:V[0-9]+)?(?![A-Za-z0-9_])",
371
+ re.IGNORECASE,
372
+ )
373
+ if python_op_pattern.search(data):
370
374
  findings.append(
371
375
  create_jit_finding(
372
376
  message="Python operator in ONNX model - can execute arbitrary code",
@@ -276,8 +276,10 @@ class SecretsDetector:
276
276
  "AKIAIOSFODNN7EXAMPLE", # AWS example access key
277
277
  "bPxRfiCYEXAMPLEKEY", # AWS example secret key
278
278
  # JWT.io example token (without signature part)
279
- "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
280
- "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ",
279
+ (
280
+ "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
281
+ "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ"
282
+ ),
281
283
  "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", # JWT.io example signature
282
284
  ]
283
285
  if any(example in text for example in example_secrets):
@@ -1,3 +1,4 @@
1
+ import itertools
1
2
  import json
2
3
  import os
3
4
  import re
@@ -115,6 +116,55 @@ UNLICENSED_INDICATORS = [
115
116
  SPDX_LICENSE_PATH = Path(__file__).parent.parent / "config" / "data" / "spdx_licenses.json"
116
117
  SPDX_LICENSE_URL = "https://raw.githubusercontent.com/spdx/license-list-data/master/json/licenses.json"
117
118
  _SPDX_LICENSES: dict[str, Any] | None = None
119
+ _LICENSE_HEADER_MAX_BYTES = 64 * 1024
120
+ _LICENSE_BINARY_CONTROL_BYTE_RATIO = 0.30
121
+ _LICENSE_TEXT_CONTROL_BYTES = frozenset({0x09, 0x0A, 0x0C, 0x0D})
122
+
123
+ _COMPILED_LICENSE_PATTERNS = tuple(
124
+ (re.compile(pattern, re.IGNORECASE | re.MULTILINE), info) for pattern, info in LICENSE_PATTERNS.items()
125
+ )
126
+ _COMPILED_COPYRIGHT_PATTERNS = tuple(
127
+ re.compile(pattern, re.IGNORECASE | re.MULTILINE) for pattern in COPYRIGHT_PATTERNS
128
+ )
129
+
130
+
131
+ def _looks_like_binary_header_sample(sample: bytes) -> bool:
132
+ """Return True when a bounded prefix is likely binary payload data."""
133
+ if not sample:
134
+ return False
135
+ if b"\x00" in sample:
136
+ return True
137
+
138
+ control_bytes = sum(1 for byte in sample if byte < 0x20 and byte not in _LICENSE_TEXT_CONTROL_BYTES)
139
+ return (control_bytes / len(sample)) >= _LICENSE_BINARY_CONTROL_BYTE_RATIO
140
+
141
+
142
+ def _read_header_text(file_path: str, max_lines: int) -> str | None:
143
+ """Read a text header while bounding binary payload scans."""
144
+ if max_lines <= 0:
145
+ return ""
146
+
147
+ try:
148
+ with open(file_path, "rb") as f:
149
+ header_sample = f.read(_LICENSE_HEADER_MAX_BYTES)
150
+ has_more_bytes = bool(header_sample) and len(header_sample) >= _LICENSE_HEADER_MAX_BYTES and bool(f.read(1))
151
+ except OSError:
152
+ return None
153
+
154
+ if _looks_like_binary_header_sample(header_sample):
155
+ return header_sample.decode("utf-8", errors="ignore")
156
+
157
+ decoded_header = header_sample.decode("utf-8", errors="ignore")
158
+ if not has_more_bytes:
159
+ return "".join(decoded_header.splitlines(keepends=True)[:max_lines])
160
+
161
+ # Likely text files should keep the original line-oriented behavior so
162
+ # long one-line headers are not silently truncated by the binary cap.
163
+ try:
164
+ with open(file_path, encoding="utf-8", errors="ignore") as f:
165
+ return "".join(itertools.islice(f, max_lines))
166
+ except OSError:
167
+ return None
118
168
 
119
169
 
120
170
  def load_spdx_license_data(download: bool = False) -> dict[str, Any]:
@@ -190,26 +240,13 @@ def scan_for_license_headers(file_path: str, max_lines: int = 50) -> list[Licens
190
240
  """
191
241
  licenses: list[LicenseInfo] = []
192
242
 
193
- try:
194
- with open(file_path, encoding="utf-8", errors="ignore") as f:
195
- content = ""
196
- for i, line in enumerate(f):
197
- if i >= max_lines:
198
- break
199
- content += line
200
- except (OSError, UnicodeDecodeError):
201
- # Try reading as binary for files that might not be text
202
- try:
203
- with open(file_path, "rb") as f:
204
- binary_content = f.read(1024 * 10) # Read first 10KB
205
- content = binary_content.decode("utf-8", errors="ignore")
206
- except Exception:
207
- return licenses
243
+ content = _read_header_text(file_path, max_lines)
244
+ if content is None:
245
+ return licenses
208
246
 
209
247
  # Search for license patterns
210
- for pattern, info in LICENSE_PATTERNS.items():
211
- matches = re.findall(pattern, content, re.IGNORECASE | re.MULTILINE)
212
- if matches:
248
+ for pattern_re, info in _COMPILED_LICENSE_PATTERNS:
249
+ if pattern_re.search(content):
213
250
  license_info = LicenseInfo(
214
251
  spdx_id=str(info["spdx_id"]) if info["spdx_id"] else None,
215
252
  name=str(info["name"]) if info["name"] else None,
@@ -240,19 +277,13 @@ def extract_copyright_notices(
240
277
  """
241
278
  copyrights: list[CopyrightInfo] = []
242
279
 
243
- try:
244
- with open(file_path, encoding="utf-8", errors="ignore") as f:
245
- content = ""
246
- for i, line in enumerate(f):
247
- if i >= max_lines:
248
- break
249
- content += line
250
- except Exception:
280
+ content = _read_header_text(file_path, max_lines)
281
+ if content is None:
251
282
  return copyrights
252
283
 
253
284
  # Search for copyright patterns
254
- for pattern in COPYRIGHT_PATTERNS:
255
- matches = re.findall(pattern, content, re.IGNORECASE | re.MULTILINE)
285
+ for pattern_re in _COMPILED_COPYRIGHT_PATTERNS:
286
+ matches = pattern_re.findall(content)
256
287
  for match in matches:
257
288
  if len(match) >= 2:
258
289
  year = match[0].strip()
@@ -437,7 +437,23 @@ class ModelAuditResultModel(BaseModel, DictCompatMixin):
437
437
  self.file_metadata[path] = metadata
438
438
 
439
439
  # Track scanner names (avoid duplicates)
440
- for scanner in results_dict.get("scanners", []):
440
+ def _normalize_scanner_names(value: Any) -> list[str]:
441
+ """Coerce scanner metadata into a list of scanner names."""
442
+ if value is None:
443
+ return []
444
+ if isinstance(value, str):
445
+ return [value]
446
+ if isinstance(value, list | tuple):
447
+ return [scanner for scanner in value if isinstance(scanner, str)]
448
+ if isinstance(value, set):
449
+ return sorted(scanner for scanner in value if isinstance(scanner, str))
450
+ return []
451
+
452
+ merged_scanners = [
453
+ *_normalize_scanner_names(results_dict.get("scanners")),
454
+ *_normalize_scanner_names(results_dict.get("scanner_names")),
455
+ ]
456
+ for scanner in merged_scanners:
441
457
  if scanner and scanner not in self.scanner_names and scanner != "unknown":
442
458
  self.scanner_names.append(scanner)
443
459
 
@@ -141,7 +141,6 @@ class ProgressReporter(ABC):
141
141
  Args:
142
142
  stats: Current progress statistics
143
143
  """
144
- pass
145
144
 
146
145
  @abstractmethod
147
146
  def report_phase_change(self, old_phase: ProgressPhase, new_phase: ProgressPhase) -> None:
@@ -151,7 +150,6 @@ class ProgressReporter(ABC):
151
150
  old_phase: Previous phase
152
151
  new_phase: New phase
153
152
  """
154
- pass
155
153
 
156
154
  @abstractmethod
157
155
  def report_completion(self, stats: ProgressStats) -> None:
@@ -160,7 +158,6 @@ class ProgressReporter(ABC):
160
158
  Args:
161
159
  stats: Final progress statistics
162
160
  """
163
- pass
164
161
 
165
162
  @abstractmethod
166
163
  def report_error(self, error: Exception, stats: ProgressStats) -> None:
@@ -170,7 +167,6 @@ class ProgressReporter(ABC):
170
167
  error: The error that occurred
171
168
  stats: Progress statistics at time of error
172
169
  """
173
- pass
174
170
 
175
171
  def should_update(self) -> bool:
176
172
  """Check if enough time has passed for an update."""