modelaudit 0.2.31__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.
- modelaudit-0.2.32/.release-please-manifest.json +3 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/CHANGELOG.md +20 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/PKG-INFO +1 -1
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/coreml_scanner.py +54 -65
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/oci_layer_scanner.py +35 -14
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/openvino_scanner.py +78 -2
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/pmml_scanner.py +3 -1
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/tensorrt_scanner.py +2 -2
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/file/detection.py +5 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/pyproject.toml +1 -1
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_coreml_scanner.py +53 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_oci_layer_scanner.py +27 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_openvino_scanner.py +56 -3
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_pmml_scanner.py +99 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_tensorrt_scanner.py +14 -1
- {modelaudit-0.2.31 → modelaudit-0.2.32}/uv.lock +666 -654
- modelaudit-0.2.31/.release-please-manifest.json +0 -3
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.dockerignore +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.editorconfig +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.gitattributes +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.github/CODEOWNERS +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.github/markdown-link-check-config.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.github/workflows/README.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.github/workflows/codeql.yml +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.github/workflows/docker-image-test.yml +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.github/workflows/docker-publish.yml +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.github/workflows/docs-check.yml +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.github/workflows/nightly.yml +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.github/workflows/perf.yml +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.github/workflows/release-please.yml +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.github/workflows/test.yml +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.github/workflows/validate-pr-title.yml +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.gitignore +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.mailmap +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.modelaudit.toml.example +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/.prettierignore +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/AGENTS.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/CLAUDE.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/CODE_OF_CONDUCT.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/CONTRIBUTING.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/Dockerfile +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/Dockerfile.full +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/Dockerfile.tensorflow +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/LICENSE +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/MAINTAINERS.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/MANIFEST.in +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/README.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/RULES.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/SECURITY.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/SUPPORT.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/THIRD_PARTY_NOTICES.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/codecov.yml +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docker-compose.yml +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docker-entrypoint.sh +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/agents/architecture.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/agents/dependencies.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/agents/new-scanner-quickstart.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/agents/release-process.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/maintainers/cve-gap-pr-plan-2026-03-20.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/maintainers/cve-process.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/maintainers/dependency-policy.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/maintainers/format-gap-plans/coreml-mlmodel.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/maintainers/format-gap-plans/mxnet-models.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/maintainers/format-gap-plans/tensorflow-metagraph.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/maintainers/format-gap-plans/torchserve-mar.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/maintainers/triage-playbook.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/security/threat-model.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/user/compatibility-matrix.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/user/metadata-extraction.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/user/offline-air-gapped.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/docs/user/security-model.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/__main__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/analysis/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/analysis/anomaly_detector.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/analysis/enhanced_pattern_detector.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/analysis/entropy_analyzer.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/analysis/framework_patterns.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/analysis/integrated_analyzer.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/analysis/ml_context_analyzer.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/analysis/opcode_sequence_analyzer.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/analysis/semantic_analyzer.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/analysis/unified_context.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/auth/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/auth/client.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/auth/config.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/cache/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/cache/adaptive_cache_keys.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/cache/batch_operations.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/cache/cache_manager.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/cache/cache_policy.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/cache/optimized_config.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/cache/scan_results_cache.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/cache/trusted_config_store.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/cli.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/config/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/config/constants.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/config/data/spdx_licenses.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/config/explanations.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/config/generated_keras_layers.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/config/local_config.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/config/name_blacklist.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/config/rule_config.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/core.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/detectors/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/detectors/cve_patterns.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/detectors/jit_script.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/detectors/network_comm.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/detectors/secrets.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/detectors/suspicious_symbols.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/integrations/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/integrations/jfrog.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/integrations/license_checker.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/integrations/mlflow.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/integrations/sarif_formatter.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/integrations/sbom_generator.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/metadata_extractor.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/models.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/progress/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/progress/base.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/progress/console.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/progress/file.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/progress/hooks.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/progress/multi_phase.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/LICENSE +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/NOTICE +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/py.typed +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/allocation_description_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/api_def_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/attr_value_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/cost_graph_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/cpp_shape_inference_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/dataset_metadata_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/dataset_options_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/dataset_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/device_attributes_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/full_type_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/function_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/graph_debug_info_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/graph_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/graph_transfer_info_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/kernel_def_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/log_memory_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/model_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/node_def_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/op_def_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/optimized_function_graph_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/reader_base_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/resource_handle_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/step_stats_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/tensor_description_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/tensor_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/tensor_shape_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/tensor_slice_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/types_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/variable_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/framework/versions_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/cluster_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/composite_tensor_variant_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/control_flow_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/core_platform_payloads_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/critical_section_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/data_service_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/debug_event_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/debug_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/device_filters_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/device_properties_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/fingerprint_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/meta_graph_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/named_tensor_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/remote_tensor_handle_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/rewriter_config_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/saved_model_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/saved_object_graph_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/saver_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/service_config_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/snapshot_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/struct_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/tensor_bundle_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/trackable_object_graph_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/transport_options_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/protos/tensorflow/core/protobuf/verifier_config_pb2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/py.typed +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/rules.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/base.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/catboost_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/cntk_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/compressed_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/executorch_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/flax_msgpack_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/gguf_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/jax_checkpoint_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/jinja2_template_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/joblib_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/keras_h5_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/keras_utils.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/keras_zip_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/lightgbm_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/llamafile_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/manifest_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/metadata_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/mxnet_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/nemo_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/numpy_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/onnx_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/paddle_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/pickle_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/pytorch_binary_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/pytorch_zip_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/r_serialized_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/rknn_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/rule_mapper.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/safetensors_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/sevenzip_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/skops_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/tar_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/text_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/tf_metagraph_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/tf_savedmodel_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/tflite_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/torch7_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/torchserve_mar_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/weight_distribution_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/xgboost_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/scanners/zip_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/telemetry.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/auto_defaults.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/file/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/file/filtering.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/file/handlers.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/file/large_file_handler.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/file/streaming.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/helpers/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/helpers/assets.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/helpers/auto_defaults.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/helpers/cache_decorator.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/helpers/code_validation.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/helpers/disk_space.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/helpers/file_hash.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/helpers/file_iterator.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/helpers/interrupt_handler.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/helpers/ml_context.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/helpers/result_conversion.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/helpers/retry.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/helpers/secure_hasher.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/helpers/types.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/lfs.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/model_extensions.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/sources/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/sources/cloud_storage.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/sources/dvc.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/sources/huggingface.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/sources/jfrog.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/sources/pytorch_hub.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/utils/tensorflow_compat.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/whitelists/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/whitelists/huggingface_organizations.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/modelaudit/whitelists/huggingface_popular.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/package-lock.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/package.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/pyproject.toml.example +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/release-please-config.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/renovate.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/scripts/README.md +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/scripts/benchmark_report.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/scripts/check_circular_imports.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/scripts/compile_tensorflow_protos.sh +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/scripts/fetch_hf_org_models.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/scripts/fetch_hf_top_models.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/scripts/generate_keras_layer_inventory.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/scripts/jax_flax_scanning_demo.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/scripts/minimal_circular_check.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/analysis/test_analysis_modules.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/analysis/test_anomaly_detector.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/analysis/test_enhanced_pattern_detector.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/analysis/test_entropy_analyzer.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/analysis/test_framework_patterns.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/analysis/test_ml_context_analyzer.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/analysis/test_opcode_sequence_analyzer.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/analysis/test_unified_context.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/exploits/exploit1_basic_torch_bypass.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/exploits/exploit2_advanced_torch_bypass.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/exploits/exploit3_sophisticated_hybrid.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/exploits/exploit4_supply_chain_attack.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/exploits/exploit5_ultra_high_confidence.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/exploits/exploit6_ordereddict_bypass.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/exploits/exploit7_nested_collections.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/exploits/exploit9_manual_construction.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/exploits/exploit_ultimate_50pct.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/generators/generate_7z_test_assets.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/generators/generate_advanced_pickle_tests.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/generators/generate_evil_pickle.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/generators/generate_jinja2_test_assets.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/generators/generate_nested_pickle_assets.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/generators/generate_os_alias_tests.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/generators/generate_safe_nested_assets.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/generators/generate_safetensors_assets.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/generators/generate_security_assets.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/pickles/bypass_pocs/gen_bypass_v4.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/pickles/memo_attack.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/pickles/multiple_stream_attack.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/pickles/nt_alias_attack.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/pickles/posix_alias_attack.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/pickles/stack_global_attack.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/archives/path_traversal.zip +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/archives/safe_model.zip +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign/chatml_format.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign/complex_legitimate.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign/conditional_system.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign/huggingface_llama.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign/simple_roles.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign/special_tokens.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign_conditional_format.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign_huggingface_chat.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign_simple_template.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/benign_template.j2 +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/edge_cases/empty_template.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/edge_cases/malformed_template.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/edge_cases/multiple_templates.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/edge_cases/no_template.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/edge_cases/oversized_template.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/attr_bypass.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/combined_attack.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/config_exploit.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/cve_2024_34359_original.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/direct_eval.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/env_extraction.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/file_access.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/hex_bypass.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/loop_discovery.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/network_exfil.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/request_exploit.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious/subprocess_injection.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious_cve_2024_34359.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious_env_vars.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious_file_read.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious_loop_exploit.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious_obfuscated.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/malicious_subprocess.template +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/obfuscated/base64_payload.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/obfuscated/char_construction.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/obfuscated/format_bypass.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/obfuscated/getattr_bypass.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/standalone/benign_chat.j2 +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/standalone/malicious_standalone.jinja +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/standalone/suspicious_benign.template +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/tokenizer_config.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/yaml/malicious_config.yaml +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/jinja2/yaml/model_config.yaml +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/keras/basic_lambda_layer.h5 +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/keras/custom_layer_attack.h5 +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/keras/keras_zip_format.keras +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/keras/lambda_exfiltration.h5 +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/keras/lambda_with_imports.h5 +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/keras/loss_injection.h5 +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/keras/malicious_lambda.h5 +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/keras/metric_injection.h5 +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/keras/safe_model.h5 +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/manifests/safe_config.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/manifests/suspicious_config.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pickles/decode_exec_chain.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pickles/dill_func.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pickles/malicious_model_realistic.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pickles/malicious_system_call.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pickles/nested_pickle_base64.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pickles/nested_pickle_hex.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pickles/nested_pickle_multistage.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pickles/nested_pickle_raw.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pickles/safe_data.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pickles/safe_large_model.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pickles/safe_model_with_binary.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pickles/safe_model_with_encoding.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pickles/safe_model_with_tokens.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pickles/safe_nested_structure.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pickles/simple_nested.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pipeline.skops +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pytorch/malicious_eval.pt +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/pytorch/safe_model.pt +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/safetensors/malicious_import.safetensors +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/safetensors/multiple_patterns.safetensors +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/safetensors/obfuscated_metadata.safetensors +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/safetensors/safe_model.safetensors +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/safetensors/script_injection.safetensors +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/safetensors/shell_commands.safetensors +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/safetensors/suspicious_url.safetensors +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/tensorflow/malicious_pyfunc/saved_model.pb +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/samples/tensorflow/safe_savedmodel/saved_model.pb +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/agpl_component/agpl_model.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/agpl_component/neural_network.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mit_model/config.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mit_model/model.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mit_model/model_weights.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mixed_licenses/LICENSE +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mixed_licenses/apache_component.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mixed_licenses/dataset_cc_nc.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mixed_licenses/gpl_utility.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/mixed_licenses/mixed_model.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/unlicensed_dataset/embeddings.npy +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/unlicensed_dataset/features.csv +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/scenarios/license_scenarios/unlicensed_dataset/training_data.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/scenarios/security_scenarios/mixed_malicious_model/config.json +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/assets/scenarios/security_scenarios/mixed_malicious_model/model.pkl +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/benchmarks/test_scan_benchmarks.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/cache/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/cache/test_cache_correctness.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/cache/test_optimized_config.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/cli_output.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/config/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/config/test_name_blacklist.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/conftest.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/demo_license_functionality.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/detectors/test_builtin_detection.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/detectors/test_compile_eval_variants.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/detectors/test_cve_detection.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/detectors/test_jit_script_detector.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/detectors/test_network_comm_detector.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/detectors/test_runpy_detection.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/detectors/test_secrets_detector.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/detectors/test_suspicious_symbols.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/helpers/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/helpers/file_creators.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/helpers/frameworks.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/integrations/test_jfrog.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/integrations/test_jfrog_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/integrations/test_license_checker.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/integrations/test_license_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/integrations/test_mlflow_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/integrations/test_sarif_formatter.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/integrations/test_sbom_license_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/integrations/test_sbom_url_fixes.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/progress/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/progress/test_base.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_base_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_catboost_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_cntk_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_compressed_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_executorch_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_flax_msgpack_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_gguf_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_jax_checkpoint_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_jinja2_template_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_joblib_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_joblib_scanner_codecs.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_keras_h5_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_keras_zip_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_lightgbm_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_llamafile_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_manifest_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_metadata_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_mxnet_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_nemo_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_numpy_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_onnx_dependency_handling.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_onnx_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_paddle_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_pickle_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_pytorch_binary_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_pytorch_zip_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_r_serialized_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_rknn_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_rule_code_registry_consistency.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_rule_mapper.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_safetensors_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_scanner_registry.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_sevenzip_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_skops_content_analysis.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_skops_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_tar_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_tf_metagraph_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_tf_savedmodel_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_tflite_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_torch7_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_torchserve_mar_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_weight_distribution_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_xgboost_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/scanners/test_zip_scanner.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_asset_inventory_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_asset_list.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_auth_config.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_basic.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_benchmark_report.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_bug1_confidence_exploit.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_cache_cli.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_cache_optimizations.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_checks_recording.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_cli.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_cli_cache_dir.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_cli_default_command.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_cli_file_filtering.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_cli_license_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_cli_logging_handlers.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_cli_output.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_cloud_url_detection.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_core.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_core_asset_extraction.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_cve_2025_10155_bin_pickle.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_debug_command.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_dill_joblib_enhanced.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_directory_file_filtering.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_double_interrupt.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_exit_codes.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_false_positive_fixes.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_file_hash.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_gguf_sbom_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_graceful_degradation.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_header_discrepancy.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_huggingface_extensions.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_huggingface_symlinks.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_importlib_detection.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_jax_flax_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_jit_script_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_lazy_loading.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_lazy_loading_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_manifest_name_policy.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_metadata_extractor.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_models.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_nested_pickle_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_network_comm_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_os_alias_detection.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_os_subprocess_detection.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_path_traversal.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_performance_benchmarks.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_pickle_context_filtering.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_progress.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_pydantic_models.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_python_version_warning.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_pytorch_zip_detection.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_real_world_dill_joblib.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_regression_corpus.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_regular_scan_hash.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_rules.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_safetensors_optimization.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_secure_hasher.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_security_asset_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_security_enhancements.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_shebang_context.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_simple_jinja2.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_sklearn_joblib_false_positive.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_streaming_scan.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_telemetry.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_telemetry_decoupling.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_tensorflow_lambda_detection.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_timeout_configuration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_utils.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_weak_hash_detection.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_webbrowser_detection.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_why_explanations.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/test_xdist_status.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/file/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/file/test_advanced_file_handler.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/file/test_advanced_size_limits.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/file/test_file_filter.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/file/test_file_type_validation_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/file/test_filetype.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/file/test_integration_file_type_demo.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/file/test_large_file_handler.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/file/test_streaming_analysis.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/file/test_streaming_preview.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/helpers/test_asset_from_scan_result.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/helpers/test_auto_defaults.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/helpers/test_code_validation.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/helpers/test_disk_space.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/helpers/test_file_iterator.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/helpers/test_interrupt_handling.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/helpers/test_ml_context_false_positives.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/helpers/test_py_compile_improvements.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/helpers/test_secure_hasher.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/sources/test_cloud_storage.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/sources/test_dvc_integration.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/sources/test_huggingface.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/sources/test_pytorch_hub.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/test_lfs.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/utils/test_result_conversion.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/whitelists/__init__.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/whitelists/test_combined.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/whitelists/test_huggingface_popular.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/whitelists/test_organizations.py +0 -0
- {modelaudit-0.2.31 → modelaudit-0.2.32}/tests/xdist_status.py +0 -0
|
@@ -5,6 +5,24 @@ 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
|
+
|
|
8
26
|
## [0.2.31](https://github.com/promptfoo/modelaudit/compare/v0.2.30...v0.2.31) (2026-04-04)
|
|
9
27
|
|
|
10
28
|
### Bug Fixes
|
|
@@ -163,6 +181,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
163
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
|
|
164
182
|
- **license:** bound binary header scans and reuse compiled patterns to avoid full-file regex passes on large model archives
|
|
165
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
|
|
166
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
|
|
167
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
|
|
168
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
|
|
@@ -180,6 +199,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
180
199
|
- preserve disguised model files during directory prefiltering without promoting document ZIPs
|
|
181
200
|
- fail closed on duplicate 7z entries, nested critical findings, probe-limit truncation, and malformed 7z safety-limit configs
|
|
182
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
|
|
183
203
|
- recurse into nested 7z members even when their filenames use misleading extensions
|
|
184
204
|
- fail closed on extreme-size files when a scanner lacks bounded large-file analysis
|
|
185
205
|
- harden scan-cache invalidation and skip caching operational scan failures
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modelaudit
|
|
3
|
-
Version: 0.2.
|
|
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
|
|
@@ -198,6 +198,7 @@ class CoreMLScanner(BaseScanner):
|
|
|
198
198
|
MAX_USER_METADATA_ENTRIES: ClassVar[int] = 512
|
|
199
199
|
MAX_RECURSIVE_MESSAGE_DEPTH: ClassVar[int] = 16
|
|
200
200
|
MAX_RECURSIVE_PROTOBUF_DEPTH: ClassVar[int] = 64
|
|
201
|
+
_allow_truncated_field_parse = False
|
|
201
202
|
|
|
202
203
|
# CoreML model oneof fields from Model.proto
|
|
203
204
|
MODEL_TYPE_FIELDS: ClassVar[frozenset[int]] = frozenset(
|
|
@@ -339,6 +340,7 @@ class CoreMLScanner(BaseScanner):
|
|
|
339
340
|
result = self._create_result()
|
|
340
341
|
self.current_file_path = path
|
|
341
342
|
file_size = self.get_file_size(path)
|
|
343
|
+
self._allow_truncated_field_parse = file_size > self.MAX_PARSE_BYTES
|
|
342
344
|
result.metadata["file_size"] = file_size
|
|
343
345
|
|
|
344
346
|
# Add file integrity check for compliance.
|
|
@@ -362,6 +364,7 @@ class CoreMLScanner(BaseScanner):
|
|
|
362
364
|
return result
|
|
363
365
|
|
|
364
366
|
if file_size > self.MAX_PARSE_BYTES:
|
|
367
|
+
result.metadata["coreml_bounded_read_truncated"] = True
|
|
365
368
|
result.add_check(
|
|
366
369
|
name="CoreML Bounded Parse Window",
|
|
367
370
|
passed=True,
|
|
@@ -438,9 +441,11 @@ class CoreMLScanner(BaseScanner):
|
|
|
438
441
|
model_path=model_path,
|
|
439
442
|
)
|
|
440
443
|
|
|
441
|
-
|
|
444
|
+
scan_truncated = bool(
|
|
445
|
+
result.metadata.get("coreml_bounded_read_truncated") or result.metadata.get("coreml_traversal_truncated")
|
|
446
|
+
)
|
|
442
447
|
|
|
443
|
-
if metadata_findings == 0 and not
|
|
448
|
+
if metadata_findings == 0 and not scan_truncated:
|
|
444
449
|
result.add_check(
|
|
445
450
|
name="CoreML Metadata Security Check",
|
|
446
451
|
passed=True,
|
|
@@ -448,7 +453,7 @@ class CoreMLScanner(BaseScanner):
|
|
|
448
453
|
location=path,
|
|
449
454
|
)
|
|
450
455
|
|
|
451
|
-
if custom_findings == 0 and not
|
|
456
|
+
if custom_findings == 0 and not scan_truncated:
|
|
452
457
|
result.add_check(
|
|
453
458
|
name="CoreML Custom Code Path Check",
|
|
454
459
|
passed=True,
|
|
@@ -456,7 +461,7 @@ class CoreMLScanner(BaseScanner):
|
|
|
456
461
|
location=path,
|
|
457
462
|
)
|
|
458
463
|
|
|
459
|
-
if linked_path_findings == 0 and not
|
|
464
|
+
if linked_path_findings == 0 and not scan_truncated:
|
|
460
465
|
result.add_check(
|
|
461
466
|
name="CoreML Linked Model Path Check",
|
|
462
467
|
passed=True,
|
|
@@ -609,6 +614,22 @@ class CoreMLScanner(BaseScanner):
|
|
|
609
614
|
"has_custom_model": has_custom_model,
|
|
610
615
|
}
|
|
611
616
|
|
|
617
|
+
def _parse_field_message(
|
|
618
|
+
self,
|
|
619
|
+
field: _ProtoField,
|
|
620
|
+
*,
|
|
621
|
+
max_fields: int,
|
|
622
|
+
) -> tuple[list[_ProtoField], str | None]:
|
|
623
|
+
payload = field.value
|
|
624
|
+
if not isinstance(payload, bytes):
|
|
625
|
+
return [], None
|
|
626
|
+
|
|
627
|
+
return _parse_message(
|
|
628
|
+
payload,
|
|
629
|
+
max_fields=max_fields,
|
|
630
|
+
allow_truncated=self._allow_truncated_field_parse and field.truncated,
|
|
631
|
+
)
|
|
632
|
+
|
|
612
633
|
def _analyze_description(
|
|
613
634
|
self,
|
|
614
635
|
top_fields: list[_ProtoField],
|
|
@@ -623,11 +644,10 @@ class CoreMLScanner(BaseScanner):
|
|
|
623
644
|
if not description_messages:
|
|
624
645
|
return findings
|
|
625
646
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
desc_fields, desc_error = _parse_message(description_payload, max_fields=self.MAX_NESTED_FIELDS)
|
|
647
|
+
desc_fields, desc_error = self._parse_field_message(
|
|
648
|
+
description_messages[0],
|
|
649
|
+
max_fields=self.MAX_NESTED_FIELDS,
|
|
650
|
+
)
|
|
631
651
|
if desc_error:
|
|
632
652
|
result.add_check(
|
|
633
653
|
name="CoreML Description Parse",
|
|
@@ -643,11 +663,10 @@ class CoreMLScanner(BaseScanner):
|
|
|
643
663
|
if not metadata_messages:
|
|
644
664
|
return findings
|
|
645
665
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
metadata_fields, metadata_error = _parse_message(metadata_payload, max_fields=self.MAX_NESTED_FIELDS)
|
|
666
|
+
metadata_fields, metadata_error = self._parse_field_message(
|
|
667
|
+
metadata_messages[0],
|
|
668
|
+
max_fields=self.MAX_NESTED_FIELDS,
|
|
669
|
+
)
|
|
651
670
|
if metadata_error:
|
|
652
671
|
result.add_check(
|
|
653
672
|
name="CoreML Metadata Parse",
|
|
@@ -694,11 +713,7 @@ class CoreMLScanner(BaseScanner):
|
|
|
694
713
|
user_defined: dict[str, str] = {}
|
|
695
714
|
user_defined_fields = _len_fields(metadata_fields, 100)[: self.MAX_USER_METADATA_ENTRIES]
|
|
696
715
|
for index, entry_field in enumerate(user_defined_fields):
|
|
697
|
-
|
|
698
|
-
if not isinstance(entry_payload, bytes):
|
|
699
|
-
continue
|
|
700
|
-
|
|
701
|
-
entry_fields, entry_error = _parse_message(entry_payload, max_fields=32)
|
|
716
|
+
entry_fields, entry_error = self._parse_field_message(entry_field, max_fields=32)
|
|
702
717
|
if entry_error:
|
|
703
718
|
result.add_check(
|
|
704
719
|
name="CoreML User Metadata Entry Parse",
|
|
@@ -862,12 +877,9 @@ class CoreMLScanner(BaseScanner):
|
|
|
862
877
|
for model_field in top_fields:
|
|
863
878
|
if model_field.field_number not in self.NEURAL_NETWORK_FIELDS or model_field.wire_type != 2:
|
|
864
879
|
continue
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
network_fields, network_error = _parse_message(
|
|
870
|
-
payload, max_fields=self.MAX_NESTED_FIELDS, allow_truncated=False
|
|
880
|
+
network_fields, network_error = self._parse_field_message(
|
|
881
|
+
model_field,
|
|
882
|
+
max_fields=self.MAX_NESTED_FIELDS,
|
|
871
883
|
)
|
|
872
884
|
if network_error:
|
|
873
885
|
result.add_check(
|
|
@@ -886,12 +898,10 @@ class CoreMLScanner(BaseScanner):
|
|
|
886
898
|
|
|
887
899
|
layer_fields = _len_fields(network_fields, 1)
|
|
888
900
|
for layer_index, layer_field in enumerate(layer_fields):
|
|
889
|
-
layer_payload = layer_field.value
|
|
890
|
-
if not isinstance(layer_payload, bytes):
|
|
891
|
-
continue
|
|
892
901
|
layer_count += 1
|
|
893
|
-
parsed_layer, layer_error =
|
|
894
|
-
|
|
902
|
+
parsed_layer, layer_error = self._parse_field_message(
|
|
903
|
+
layer_field,
|
|
904
|
+
max_fields=self.MAX_NESTED_FIELDS,
|
|
895
905
|
)
|
|
896
906
|
if layer_error:
|
|
897
907
|
result.add_check(
|
|
@@ -917,14 +927,10 @@ class CoreMLScanner(BaseScanner):
|
|
|
917
927
|
|
|
918
928
|
custom_fields = _len_fields(parsed_layer, 500)
|
|
919
929
|
for custom_field in custom_fields:
|
|
920
|
-
custom_payload = custom_field.value
|
|
921
|
-
if not isinstance(custom_payload, bytes):
|
|
922
|
-
continue
|
|
923
930
|
custom_layer_count += 1
|
|
924
|
-
parsed_custom, custom_error =
|
|
925
|
-
|
|
931
|
+
parsed_custom, custom_error = self._parse_field_message(
|
|
932
|
+
custom_field,
|
|
926
933
|
max_fields=self.MAX_NESTED_FIELDS,
|
|
927
|
-
allow_truncated=False,
|
|
928
934
|
)
|
|
929
935
|
if custom_error:
|
|
930
936
|
result.add_check(
|
|
@@ -979,12 +985,9 @@ class CoreMLScanner(BaseScanner):
|
|
|
979
985
|
|
|
980
986
|
custom_model_fields = _len_fields(top_fields, self.CUSTOM_MODEL_FIELD)
|
|
981
987
|
for custom_model_field in custom_model_fields:
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
custom_model, custom_model_error = _parse_message(
|
|
987
|
-
payload, max_fields=self.MAX_NESTED_FIELDS, allow_truncated=False
|
|
988
|
+
custom_model, custom_model_error = self._parse_field_message(
|
|
989
|
+
custom_model_field,
|
|
990
|
+
max_fields=self.MAX_NESTED_FIELDS,
|
|
988
991
|
)
|
|
989
992
|
if custom_model_error:
|
|
990
993
|
result.add_check(
|
|
@@ -1053,11 +1056,7 @@ class CoreMLScanner(BaseScanner):
|
|
|
1053
1056
|
|
|
1054
1057
|
parameter_entries = _len_fields(message_fields, 30)
|
|
1055
1058
|
for entry_index, parameter_entry in enumerate(parameter_entries):
|
|
1056
|
-
|
|
1057
|
-
if not isinstance(entry_payload, bytes):
|
|
1058
|
-
continue
|
|
1059
|
-
|
|
1060
|
-
entry_fields, entry_error = _parse_message(entry_payload, max_fields=32, allow_truncated=False)
|
|
1059
|
+
entry_fields, entry_error = self._parse_field_message(parameter_entry, max_fields=32)
|
|
1061
1060
|
if entry_error:
|
|
1062
1061
|
result.add_check(
|
|
1063
1062
|
name="CoreML Custom Parameter Entry Parse",
|
|
@@ -1079,12 +1078,11 @@ class CoreMLScanner(BaseScanner):
|
|
|
1079
1078
|
continue
|
|
1080
1079
|
|
|
1081
1080
|
raw_key = key_fields[0].value
|
|
1082
|
-
|
|
1083
|
-
if not isinstance(raw_key, bytes) or not isinstance(raw_value, bytes):
|
|
1081
|
+
if not isinstance(raw_key, bytes):
|
|
1084
1082
|
continue
|
|
1085
1083
|
|
|
1086
1084
|
param_key = _decode_string(raw_key, max_length=256)
|
|
1087
|
-
value_message_fields, value_error =
|
|
1085
|
+
value_message_fields, value_error = self._parse_field_message(value_fields[0], max_fields=32)
|
|
1088
1086
|
if value_error:
|
|
1089
1087
|
result.add_check(
|
|
1090
1088
|
name="CoreML Custom Parameter Value Parse",
|
|
@@ -1151,11 +1149,7 @@ class CoreMLScanner(BaseScanner):
|
|
|
1151
1149
|
|
|
1152
1150
|
base_dir = Path(path).resolve().parent
|
|
1153
1151
|
for linked_model_field in linked_model_fields:
|
|
1154
|
-
|
|
1155
|
-
if not isinstance(payload, bytes):
|
|
1156
|
-
continue
|
|
1157
|
-
|
|
1158
|
-
linked_model_message, parse_error = _parse_message(payload, max_fields=64, allow_truncated=False)
|
|
1152
|
+
linked_model_message, parse_error = self._parse_field_message(linked_model_field, max_fields=64)
|
|
1159
1153
|
if parse_error:
|
|
1160
1154
|
result.add_check(
|
|
1161
1155
|
name="CoreML Linked Model Parse",
|
|
@@ -1173,11 +1167,10 @@ class CoreMLScanner(BaseScanner):
|
|
|
1173
1167
|
|
|
1174
1168
|
linked_model_file_fields = _len_fields(linked_model_message, 1)
|
|
1175
1169
|
for linked_model_file_field in linked_model_file_fields:
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
linked_model_file, file_error = _parse_message(file_payload, max_fields=64, allow_truncated=False)
|
|
1170
|
+
linked_model_file, file_error = self._parse_field_message(
|
|
1171
|
+
linked_model_file_field,
|
|
1172
|
+
max_fields=64,
|
|
1173
|
+
)
|
|
1181
1174
|
if file_error:
|
|
1182
1175
|
result.add_check(
|
|
1183
1176
|
name="CoreML Linked Model File Parse",
|
|
@@ -1225,11 +1218,7 @@ class CoreMLScanner(BaseScanner):
|
|
|
1225
1218
|
if not parameter_fields:
|
|
1226
1219
|
return None
|
|
1227
1220
|
|
|
1228
|
-
|
|
1229
|
-
if not isinstance(payload, bytes):
|
|
1230
|
-
return None
|
|
1231
|
-
|
|
1232
|
-
parsed_parameter, parse_error = _parse_message(payload, max_fields=16, allow_truncated=False)
|
|
1221
|
+
parsed_parameter, parse_error = self._parse_field_message(parameter_fields[0], max_fields=16)
|
|
1233
1222
|
if parse_error:
|
|
1234
1223
|
return None
|
|
1235
1224
|
|
|
@@ -110,6 +110,40 @@ class OciLayerScanner(BaseScanner):
|
|
|
110
110
|
"""Trim manifest layer refs so cosmetic suffix whitespace cannot hide .tar.gz layers."""
|
|
111
111
|
return layer_ref.strip().rstrip(" .")
|
|
112
112
|
|
|
113
|
+
@classmethod
|
|
114
|
+
def _collect_layer_paths(cls, manifest_data: Any) -> list[str]:
|
|
115
|
+
"""Collect layer refs from manifest layer fields without treating arbitrary strings as layers."""
|
|
116
|
+
layer_paths: list[str] = []
|
|
117
|
+
|
|
118
|
+
def _append_layer_ref(value: Any) -> None:
|
|
119
|
+
if isinstance(value, str) and cls._normalize_layer_ref(value).lower().endswith(cls._LAYER_ARCHIVE_SUFFIX):
|
|
120
|
+
layer_paths.append(value)
|
|
121
|
+
|
|
122
|
+
def _collect_layer_value(value: Any) -> None:
|
|
123
|
+
if isinstance(value, str):
|
|
124
|
+
_append_layer_ref(value)
|
|
125
|
+
elif isinstance(value, list):
|
|
126
|
+
for item in value:
|
|
127
|
+
_collect_layer_value(item)
|
|
128
|
+
elif isinstance(value, dict):
|
|
129
|
+
for key, item in value.items():
|
|
130
|
+
if str(key).lower() in {"layers", "urls"}:
|
|
131
|
+
_collect_layer_value(item)
|
|
132
|
+
|
|
133
|
+
def _walk_manifest(obj: Any) -> None:
|
|
134
|
+
if isinstance(obj, dict):
|
|
135
|
+
for key, value in obj.items():
|
|
136
|
+
if str(key).lower() == "layers":
|
|
137
|
+
_collect_layer_value(value)
|
|
138
|
+
elif isinstance(value, (dict, list)):
|
|
139
|
+
_walk_manifest(value)
|
|
140
|
+
elif isinstance(obj, list):
|
|
141
|
+
for item in obj:
|
|
142
|
+
_walk_manifest(item)
|
|
143
|
+
|
|
144
|
+
_walk_manifest(manifest_data)
|
|
145
|
+
return layer_paths
|
|
146
|
+
|
|
113
147
|
@staticmethod
|
|
114
148
|
def _rewrite_embedded_location(
|
|
115
149
|
location: str | None,
|
|
@@ -233,20 +267,7 @@ class OciLayerScanner(BaseScanner):
|
|
|
233
267
|
result.finish(success=False)
|
|
234
268
|
return result
|
|
235
269
|
|
|
236
|
-
|
|
237
|
-
layer_paths: list[str] = []
|
|
238
|
-
|
|
239
|
-
def _search(obj: Any) -> None:
|
|
240
|
-
if isinstance(obj, dict):
|
|
241
|
-
for v in obj.values():
|
|
242
|
-
_search(v)
|
|
243
|
-
elif isinstance(obj, list):
|
|
244
|
-
for item in obj:
|
|
245
|
-
_search(item)
|
|
246
|
-
elif isinstance(obj, str) and self._normalize_layer_ref(obj).lower().endswith(self._LAYER_ARCHIVE_SUFFIX):
|
|
247
|
-
layer_paths.append(obj)
|
|
248
|
-
|
|
249
|
-
_search(manifest_data)
|
|
270
|
+
layer_paths = self._collect_layer_paths(manifest_data)
|
|
250
271
|
|
|
251
272
|
manifest_dir = os.path.dirname(path)
|
|
252
273
|
scan_complete = True
|
|
@@ -40,6 +40,77 @@ def _local_tag_name(tag: str) -> str:
|
|
|
40
40
|
return tag.rsplit("}", 1)[-1].lower()
|
|
41
41
|
|
|
42
42
|
|
|
43
|
+
def _skip_doctype_declaration(xml_prefix: bytes, start_offset: int) -> int | None:
|
|
44
|
+
"""Skip a DOCTYPE declaration without expanding entities."""
|
|
45
|
+
index = start_offset + len(b"<!DOCTYPE")
|
|
46
|
+
bracket_depth = 0
|
|
47
|
+
quote_char: int | None = None
|
|
48
|
+
|
|
49
|
+
while index < len(xml_prefix):
|
|
50
|
+
byte = xml_prefix[index]
|
|
51
|
+
if quote_char is not None:
|
|
52
|
+
if byte == quote_char:
|
|
53
|
+
quote_char = None
|
|
54
|
+
elif byte in {ord("'"), ord('"')}:
|
|
55
|
+
quote_char = byte
|
|
56
|
+
elif byte == ord("["):
|
|
57
|
+
bracket_depth += 1
|
|
58
|
+
elif byte == ord("]") and bracket_depth > 0:
|
|
59
|
+
bracket_depth -= 1
|
|
60
|
+
elif byte == ord(">") and bracket_depth == 0:
|
|
61
|
+
return index + 1
|
|
62
|
+
index += 1
|
|
63
|
+
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _looks_like_openvino_xml_prefix(xml_prefix: bytes) -> bool:
|
|
68
|
+
"""Sniff the first root element without relying on entity-expanding XML parsing."""
|
|
69
|
+
index = 3 if xml_prefix.startswith(b"\xef\xbb\xbf") else 0
|
|
70
|
+
prefix_length = len(xml_prefix)
|
|
71
|
+
|
|
72
|
+
while index < prefix_length:
|
|
73
|
+
while index < prefix_length and chr(xml_prefix[index]).isspace():
|
|
74
|
+
index += 1
|
|
75
|
+
|
|
76
|
+
if xml_prefix.startswith(b"<?", index):
|
|
77
|
+
end_offset = xml_prefix.find(b"?>", index + 2)
|
|
78
|
+
if end_offset == -1:
|
|
79
|
+
return False
|
|
80
|
+
index = end_offset + 2
|
|
81
|
+
continue
|
|
82
|
+
|
|
83
|
+
if xml_prefix.startswith(b"<!--", index):
|
|
84
|
+
end_offset = xml_prefix.find(b"-->", index + 4)
|
|
85
|
+
if end_offset == -1:
|
|
86
|
+
return False
|
|
87
|
+
index = end_offset + 3
|
|
88
|
+
continue
|
|
89
|
+
|
|
90
|
+
if xml_prefix[index : index + len(b"<!DOCTYPE")].upper() == b"<!DOCTYPE":
|
|
91
|
+
next_index = _skip_doctype_declaration(xml_prefix, index)
|
|
92
|
+
if next_index is None:
|
|
93
|
+
return False
|
|
94
|
+
index = next_index
|
|
95
|
+
continue
|
|
96
|
+
|
|
97
|
+
break
|
|
98
|
+
|
|
99
|
+
if index >= prefix_length or xml_prefix[index : index + 1] != b"<":
|
|
100
|
+
return False
|
|
101
|
+
if xml_prefix[index + 1 : index + 2] in {b"/", b"!", b"?"}:
|
|
102
|
+
return False
|
|
103
|
+
|
|
104
|
+
tag_end = index + 1
|
|
105
|
+
while tag_end < prefix_length and xml_prefix[tag_end : tag_end + 1] not in b" \t\r\n\f/>":
|
|
106
|
+
tag_end += 1
|
|
107
|
+
if tag_end == index + 1:
|
|
108
|
+
return False
|
|
109
|
+
|
|
110
|
+
root_tag = xml_prefix[index + 1 : tag_end].decode("utf-8", "ignore")
|
|
111
|
+
return _local_tag_name(root_tag) in _OPENVINO_ROOT_TAGS
|
|
112
|
+
|
|
113
|
+
|
|
43
114
|
def _iter_element_attributes(layer: Any) -> Iterator[tuple[str, str, str]]:
|
|
44
115
|
"""Yield normalized attributes from a layer and its nested config nodes."""
|
|
45
116
|
for element in layer.iter():
|
|
@@ -68,8 +139,11 @@ class OpenVinoScanner(BaseScanner):
|
|
|
68
139
|
try:
|
|
69
140
|
with open(path, "rb") as xml_file:
|
|
70
141
|
xml_prefix = xml_file.read(cls.CAN_HANDLE_MAX_PARSE_BYTES)
|
|
71
|
-
|
|
72
|
-
|
|
142
|
+
try:
|
|
143
|
+
for _event, element in DefusedET.iterparse(BytesIO(xml_prefix), events=("start",)):
|
|
144
|
+
return _local_tag_name(str(element.tag)) in _OPENVINO_ROOT_TAGS
|
|
145
|
+
except Exception:
|
|
146
|
+
return _looks_like_openvino_xml_prefix(xml_prefix)
|
|
73
147
|
except Exception:
|
|
74
148
|
return False
|
|
75
149
|
|
|
@@ -105,6 +179,8 @@ class OpenVinoScanner(BaseScanner):
|
|
|
105
179
|
tree = DefusedET.parse(path)
|
|
106
180
|
root = tree.getroot()
|
|
107
181
|
except Exception as e: # pragma: no cover - parse errors
|
|
182
|
+
result.metadata["operational_error"] = True
|
|
183
|
+
result.metadata["operational_error_reason"] = "openvino_xml_parse_failed"
|
|
108
184
|
result.add_check(
|
|
109
185
|
name="OpenVINO XML Parse",
|
|
110
186
|
passed=False,
|
|
@@ -27,7 +27,9 @@ SUSPICIOUS_PATTERNS = [
|
|
|
27
27
|
r"exec\s*\(",
|
|
28
28
|
r"eval\s*\(",
|
|
29
29
|
r"import\s+os",
|
|
30
|
-
r"subprocess",
|
|
30
|
+
r"\b(?:importlib\s*\.\s*)?import_module\s*\(\s*['\"]subprocess['\"]\s*\)",
|
|
31
|
+
r"\b(?:from\s+subprocess\s+import|import\s+subprocess)\b",
|
|
32
|
+
r"\bsubprocess\s*\.\s*(?:popen|run|call|check_call|check_output|getoutput|getstatusoutput)\s*\(",
|
|
31
33
|
r"__import__",
|
|
32
34
|
r"system\s*\(",
|
|
33
35
|
]
|
|
@@ -11,11 +11,11 @@ from .base import BaseScanner, IssueSeverity, ScanResult
|
|
|
11
11
|
|
|
12
12
|
SUSPICIOUS_PATTERN_RULES: tuple[tuple[str, re.Pattern[str]], ...] = (
|
|
13
13
|
("../", re.compile(r"(?<![A-Za-z0-9_.-])(?:\.\./|\.\.\\)", re.IGNORECASE)),
|
|
14
|
-
("/tmp/", re.compile(r"(
|
|
14
|
+
("/tmp/", re.compile(r"(?<![A-Za-z0-9_.-])(?:/tmp/|(?:[A-Za-z]:)?\\tmp\\)", re.IGNORECASE)),
|
|
15
15
|
(
|
|
16
16
|
".so",
|
|
17
17
|
re.compile(
|
|
18
|
-
r"(?<![A-Za-z0-9_.-])(?:[A-Za-z0-9_+.-]+)?\.so(?:\.[
|
|
18
|
+
r"(?<![A-Za-z0-9_.-])(?:[A-Za-z0-9_+.-]+)?\.so(?:\.[0-9]+(?:\.[0-9]+)*)?(?![A-Za-z0-9_.-])",
|
|
19
19
|
re.IGNORECASE,
|
|
20
20
|
),
|
|
21
21
|
),
|
|
@@ -1382,6 +1382,11 @@ def validate_file_type(path: str) -> bool:
|
|
|
1382
1382
|
if ext_format == "pmml" and header_format == "pmml":
|
|
1383
1383
|
return True
|
|
1384
1384
|
|
|
1385
|
+
# OpenVINO IR XML can be identified structurally by the dedicated scanner
|
|
1386
|
+
# even when bounded magic-byte detection returns unknown for normal XML.
|
|
1387
|
+
if ext_format == "openvino":
|
|
1388
|
+
return header_format in {"openvino", "unknown"}
|
|
1389
|
+
|
|
1385
1390
|
if ext_format == "torchserve_mar":
|
|
1386
1391
|
return header_format == "torchserve_mar"
|
|
1387
1392
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "modelaudit"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.32"
|
|
8
8
|
description = "Static scanning library for detecting malicious code, backdoors, and other security risks in ML model files"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Ian Webster", email = "ian@promptfoo.dev" },
|
|
@@ -539,6 +539,30 @@ def test_coreml_scanner_recursion_limit_succeeds_just_below_limit(tmp_path: Path
|
|
|
539
539
|
)
|
|
540
540
|
|
|
541
541
|
|
|
542
|
+
def test_coreml_scanner_oversized_truncated_benign_layers_do_not_fail_closed(tmp_path: Path) -> None:
|
|
543
|
+
oversized_layer = _build_layer("safe_layer_" + "A" * (CoreMLScanner.MAX_PARSE_BYTES + 2048))
|
|
544
|
+
model_path = _write_model(
|
|
545
|
+
tmp_path / "oversized_truncated_benign.mlmodel",
|
|
546
|
+
_build_model(
|
|
547
|
+
description=_build_description(metadata=_build_metadata()),
|
|
548
|
+
neural_network=_build_neural_network(layers=[oversized_layer]),
|
|
549
|
+
),
|
|
550
|
+
)
|
|
551
|
+
|
|
552
|
+
result = CoreMLScanner().scan(str(model_path))
|
|
553
|
+
|
|
554
|
+
assert result.success is True
|
|
555
|
+
assert result.metadata.get("coreml_bounded_read_truncated") is True
|
|
556
|
+
assert not any(
|
|
557
|
+
issue.severity == IssueSeverity.CRITICAL and "Unable to parse CoreML neural network block" in issue.message
|
|
558
|
+
for issue in result.issues
|
|
559
|
+
)
|
|
560
|
+
assert any(
|
|
561
|
+
check.name == "CoreML Bounded Parse Window" and check.status.value == "passed" for check in result.checks
|
|
562
|
+
)
|
|
563
|
+
assert not any(check.name == "CoreML Custom Code Path Check" for check in result.checks)
|
|
564
|
+
|
|
565
|
+
|
|
542
566
|
def test_coreml_scanner_malformed_custom_model_fails_closed(tmp_path: Path) -> None:
|
|
543
567
|
model_path = _write_model(
|
|
544
568
|
tmp_path / "malformed_custom_model.mlmodel",
|
|
@@ -581,6 +605,35 @@ def test_coreml_scanner_truncated_linked_model_file_fails_closed(tmp_path: Path)
|
|
|
581
605
|
)
|
|
582
606
|
|
|
583
607
|
|
|
608
|
+
def test_coreml_scanner_truncated_nested_linked_model_fails_closed_without_bounded_read(tmp_path: Path) -> None:
|
|
609
|
+
malformed_nested_model = (
|
|
610
|
+
_field_varint(1, 8)
|
|
611
|
+
+ _field_bytes(2, _build_description(metadata=_build_metadata()))
|
|
612
|
+
+ _encode_varint((556 << 3) | 2)
|
|
613
|
+
+ _encode_varint(8)
|
|
614
|
+
+ b"\x0a\x05abc"
|
|
615
|
+
)
|
|
616
|
+
model_path = _write_model(
|
|
617
|
+
tmp_path / "nested_malformed_linked_model.mlmodel",
|
|
618
|
+
_build_model(
|
|
619
|
+
description=_build_description(metadata=_build_metadata()),
|
|
620
|
+
pipeline_wrapper=_build_pipeline_wrapper(malformed_nested_model),
|
|
621
|
+
),
|
|
622
|
+
)
|
|
623
|
+
|
|
624
|
+
result = CoreMLScanner().scan(str(model_path))
|
|
625
|
+
|
|
626
|
+
assert result.success is False
|
|
627
|
+
assert result.metadata.get("coreml_bounded_read_truncated") is not True
|
|
628
|
+
assert any(
|
|
629
|
+
issue.severity == IssueSeverity.CRITICAL
|
|
630
|
+
and "Unable to parse CoreML linked-model block" in issue.message
|
|
631
|
+
and "][1:0][556]" in issue.details.get("field_path", "")
|
|
632
|
+
and issue.details.get("parse_error") == "truncated length-delimited field 1"
|
|
633
|
+
for issue in result.issues
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
|
|
584
637
|
def test_coreml_scanner_corrupt_protobuf_handling(tmp_path: Path) -> None:
|
|
585
638
|
corrupt_path = tmp_path / "corrupt.mlmodel"
|
|
586
639
|
# Truncated length-delimited field
|
|
@@ -294,6 +294,33 @@ class TestOciLayerScanner:
|
|
|
294
294
|
|
|
295
295
|
assert result.success is True
|
|
296
296
|
|
|
297
|
+
def test_scan_manifest_ignores_non_layer_tar_gz_metadata_strings(self, tmp_path: Path) -> None:
|
|
298
|
+
"""Metadata URLs ending in .tar.gz should not be treated as required local layer files."""
|
|
299
|
+
safe_file = tmp_path / "safe.txt"
|
|
300
|
+
safe_file.write_text("Safe content")
|
|
301
|
+
|
|
302
|
+
layer_path = tmp_path / "layer.tar.gz"
|
|
303
|
+
with tarfile.open(layer_path, "w:gz") as tar:
|
|
304
|
+
tar.add(safe_file, arcname="safe.txt")
|
|
305
|
+
|
|
306
|
+
manifest = {
|
|
307
|
+
"layers": ["layer.tar.gz"],
|
|
308
|
+
"homepage": "https://cdn.example.com/not-a-local-layer.tar.gz",
|
|
309
|
+
"metadata": {
|
|
310
|
+
"release_notes": "https://cdn.example.com/docs.tar.gz",
|
|
311
|
+
"labels": ["stable", "https://cdn.example.com/archive.tar.gz"],
|
|
312
|
+
},
|
|
313
|
+
}
|
|
314
|
+
manifest_path = tmp_path / "metadata-url.manifest"
|
|
315
|
+
manifest_path.write_text(json.dumps(manifest))
|
|
316
|
+
|
|
317
|
+
result = OciLayerScanner().scan(str(manifest_path))
|
|
318
|
+
|
|
319
|
+
assert result.success is True
|
|
320
|
+
assert not any("not-a-local-layer.tar.gz" in issue.message for issue in result.issues)
|
|
321
|
+
assert not any("docs.tar.gz" in issue.message for issue in result.issues)
|
|
322
|
+
assert not any("archive.tar.gz" in issue.message for issue in result.issues)
|
|
323
|
+
|
|
297
324
|
def test_scan_layer_with_non_scannable_files(self, tmp_path):
|
|
298
325
|
"""Test scanning layer containing files that don't match any scanner."""
|
|
299
326
|
# Create a random binary file
|