genesis-flow 1.0.7__py3-none-any.whl → 1.0.8__py3-none-any.whl
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.
- {genesis_flow-1.0.7.dist-info → genesis_flow-1.0.8.dist-info}/METADATA +28 -3
- {genesis_flow-1.0.7.dist-info → genesis_flow-1.0.8.dist-info}/RECORD +8 -8
- mlflow/pyfunc/model.py +41 -16
- mlflow/utils/secure_loading.py +53 -4
- {genesis_flow-1.0.7.dist-info → genesis_flow-1.0.8.dist-info}/WHEEL +0 -0
- {genesis_flow-1.0.7.dist-info → genesis_flow-1.0.8.dist-info}/entry_points.txt +0 -0
- {genesis_flow-1.0.7.dist-info → genesis_flow-1.0.8.dist-info}/licenses/LICENSE.txt +0 -0
- {genesis_flow-1.0.7.dist-info → genesis_flow-1.0.8.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: genesis-flow
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.8
|
4
4
|
Summary: Genesis-Flow: MLflow v3.1.4 compatible fork for Genesis platform
|
5
5
|
Maintainer-email: Databricks <mlflow-oss-maintainers@googlegroups.com>
|
6
6
|
License: Copyright 2018 Databricks, Inc. All rights reserved.
|
@@ -378,6 +378,10 @@ poetry install --with dev
|
|
378
378
|
|
379
379
|
```python
|
380
380
|
import mlflow
|
381
|
+
import os
|
382
|
+
|
383
|
+
# Optional: Disable secure model loading if you encounter loading issues
|
384
|
+
# os.environ["MLFLOW_ENABLE_SECURE_MODEL_LOADING"] = "false"
|
381
385
|
|
382
386
|
# Set tracking URI (supports file, PostgreSQL, etc.)
|
383
387
|
mlflow.set_tracking_uri("file:///path/to/mlruns")
|
@@ -504,7 +508,7 @@ export MLFLOW_POSTGRES_USERNAME="user@tenant"
|
|
504
508
|
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
|
505
509
|
|
506
510
|
# Security configuration
|
507
|
-
export MLFLOW_ENABLE_SECURE_MODEL_LOADING=true
|
511
|
+
export MLFLOW_ENABLE_SECURE_MODEL_LOADING=true # Can be set to false if model loading fails
|
508
512
|
export MLFLOW_STRICT_INPUT_VALIDATION=true
|
509
513
|
```
|
510
514
|
|
@@ -761,11 +765,32 @@ entry_points = {
|
|
761
765
|
|
762
766
|
- ✅ **Input validation** against injection attacks
|
763
767
|
- ✅ **Path traversal protection** for file operations
|
764
|
-
- ✅ **Secure pickle loading** with restricted unpickling
|
768
|
+
- ✅ **Secure pickle loading** with restricted unpickling (configurable via `MLFLOW_ENABLE_SECURE_MODEL_LOADING`)
|
765
769
|
- ✅ **Authentication hooks** for enterprise SSO integration
|
766
770
|
- ✅ **Audit logging** for compliance requirements
|
767
771
|
- ✅ **Encrypted communication** support
|
768
772
|
|
773
|
+
#### Secure Model Loading Configuration
|
774
|
+
|
775
|
+
Genesis-Flow includes enhanced security for model loading that prevents arbitrary code execution from untrusted pickle files. This feature can be configured using the `MLFLOW_ENABLE_SECURE_MODEL_LOADING` environment variable:
|
776
|
+
|
777
|
+
```bash
|
778
|
+
# Enable secure model loading (default - recommended for production)
|
779
|
+
export MLFLOW_ENABLE_SECURE_MODEL_LOADING=true
|
780
|
+
|
781
|
+
# Disable secure model loading (use with caution - only for trusted models)
|
782
|
+
export MLFLOW_ENABLE_SECURE_MODEL_LOADING=false
|
783
|
+
```
|
784
|
+
|
785
|
+
**When to disable secure loading:**
|
786
|
+
- When loading legacy models that contain custom classes not in the allowlist
|
787
|
+
- During development with trusted model sources
|
788
|
+
- When migrating from standard MLflow with complex custom models
|
789
|
+
|
790
|
+
**Security implications:**
|
791
|
+
- When enabled: Only whitelisted classes can be deserialized, preventing arbitrary code execution
|
792
|
+
- When disabled: Standard cloudpickle behavior, any Python object can be loaded (potential security risk)
|
793
|
+
|
769
794
|
### Security Best Practices
|
770
795
|
|
771
796
|
1. **Use MongoDB authentication** in production
|
@@ -1,4 +1,4 @@
|
|
1
|
-
genesis_flow-1.0.
|
1
|
+
genesis_flow-1.0.8.dist-info/licenses/LICENSE.txt,sha256=Y5U1Xebzka__NZlqMPtBsYm0mRpMtUmTrONatpoL-ig,11382
|
2
2
|
mlflow/__init__.py,sha256=-_r__N5Afed81pLVtr2wKbHQIA0aj9u9n_7kWGxLWi4,11194
|
3
3
|
mlflow/__main__.py,sha256=_PcdoxKehR_a2MI6GqBfzYzRCXZhVyDCSdbxDWVlWd4,39
|
4
4
|
mlflow/cli.py,sha256=f1ObrWZ03HgRiRoVEE1Gffe-dGcSY7CxJyEFgb5VUMM,26137
|
@@ -311,7 +311,7 @@ mlflow/pyfunc/backend.py,sha256=5-tjUnY1nPecoNCxFjhLjPbhHsDGR9_0P9ym02_J3HA,2077
|
|
311
311
|
mlflow/pyfunc/context.py,sha256=nXQcP61XR7cKx6CeFsdAM4TD-NOrIEt_GQSfJ990xc4,3007
|
312
312
|
mlflow/pyfunc/dbconnect_artifact_cache.py,sha256=-Ji_GU-NLvGyxYrOFhR81SYn4E6ykiFcZl35hRQ9c6A,5769
|
313
313
|
mlflow/pyfunc/mlserver.py,sha256=ER7tXcOZ-tAUblMbgqPVT2E8BtBGH1HXLSSOmsQUB_c,1271
|
314
|
-
mlflow/pyfunc/model.py,sha256=
|
314
|
+
mlflow/pyfunc/model.py,sha256=by6xBLOmu1D1B0sH9B2LpVe6TjS14D0sStE60iJ9ofk,65686
|
315
315
|
mlflow/pyfunc/spark_model_cache.py,sha256=sFFAi-LxXEJdqk8szm32XxK5IFsISpxxVjAWjWbHZ1U,2091
|
316
316
|
mlflow/pyfunc/stdin_server.py,sha256=gNkWxlCz3KLu6jvZNeNytmKAy4j5gIXOpIehrizm43s,1362
|
317
317
|
mlflow/pyfunc/loaders/__init__.py,sha256=W3Bny093PoREOCqavIzKJ3lYeZUBXhxk3EDkCqc_lBc,276
|
@@ -613,7 +613,7 @@ mlflow/utils/requirements_utils.py,sha256=79BL9iFqg9H4VRYiqk-gTLlrfLyUY7KVG4BDV8
|
|
613
613
|
mlflow/utils/rest_utils.py,sha256=R5MZk0Ck358VeW-DKqpfSyDHbWjg_slQTpRfr4ZLDLM,26664
|
614
614
|
mlflow/utils/search_logged_model_utils.py,sha256=JWczQxogo4u9Gr3gfoSVf7tVny1e-rxfAchh3Vqy6RU,4289
|
615
615
|
mlflow/utils/search_utils.py,sha256=PgXtwlViHvmahY63otykh5iJVW0PR9DIwetrvCCBw2U,86142
|
616
|
-
mlflow/utils/secure_loading.py,sha256=
|
616
|
+
mlflow/utils/secure_loading.py,sha256=X4AdKHDkIzMvriFwCvTPLhN-yPbqs6dgUOB244Q_gRM,11892
|
617
617
|
mlflow/utils/security_validation.py,sha256=cLBrLNOoVJuAffO677v0m_v4i-01v7aLk-sJk87mpkQ,12830
|
618
618
|
mlflow/utils/server_cli_utils.py,sha256=gbT5CVkOLorSw-y8bnNSBEP9mClcVTagtTN5SK5Azhw,2381
|
619
619
|
mlflow/utils/spark_utils.py,sha256=zUbQIRAtwyU3rDJK8m7v42KO2TSGn28Coe_UYBEhIWA,395
|
@@ -641,8 +641,8 @@ mlflow/utils/autologging_utils/metrics_queue.py,sha256=bwpMX7Go6xFxrpYROi6rDBdVt
|
|
641
641
|
mlflow/utils/autologging_utils/safety.py,sha256=IwbTbusyE87Hc4qkhhvMikoaZqX9kpr972FWS2B8goc,51465
|
642
642
|
mlflow/utils/autologging_utils/versioning.py,sha256=2hSN4KXFWEJCcopDdLG6BiPeqSoqjETeNMuUBsCCwlI,3762
|
643
643
|
mlflow/utils/import_hooks/__init__.py,sha256=werje98Woelkbwrhtlb8wmRdt3RtiL--LqGru7Xh3YU,13589
|
644
|
-
genesis_flow-1.0.
|
645
|
-
genesis_flow-1.0.
|
646
|
-
genesis_flow-1.0.
|
647
|
-
genesis_flow-1.0.
|
648
|
-
genesis_flow-1.0.
|
644
|
+
genesis_flow-1.0.8.dist-info/METADATA,sha256=tam5UxyijS6-7TN_92L9-e7BHQKsKtpyNoMBhCCNGLw,34630
|
645
|
+
genesis_flow-1.0.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
646
|
+
genesis_flow-1.0.8.dist-info/entry_points.txt,sha256=YZZiTHSYQpv8vou6gdqWI17piK9Pm0P3BmZ-xepUtnw,449
|
647
|
+
genesis_flow-1.0.8.dist-info/top_level.txt,sha256=wm8UqYyUHI21EvrTDHb3eYICy0dOVDLBhAL-jp5zbuI,7
|
648
|
+
genesis_flow-1.0.8.dist-info/RECORD,,
|
mlflow/pyfunc/model.py
CHANGED
@@ -819,27 +819,52 @@ def _maybe_compress_cloudpickle_dump(python_model, path, compression):
|
|
819
819
|
|
820
820
|
def _maybe_decompress_cloudpickle_load(path, compression):
|
821
821
|
"""
|
822
|
-
Genesis-Flow:
|
822
|
+
Genesis-Flow: Model loading with optional security checks.
|
823
|
+
|
824
|
+
Security can be disabled by setting MLFLOW_ENABLE_SECURE_MODEL_LOADING=false
|
825
|
+
Default behavior is secure loading (enabled).
|
823
826
|
"""
|
824
|
-
|
827
|
+
import os
|
828
|
+
import cloudpickle
|
825
829
|
|
826
830
|
_check_compression_supported(compression)
|
827
831
|
|
828
|
-
#
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
832
|
+
# Check if secure loading should be used (default: true for security)
|
833
|
+
use_secure_loading = os.getenv('MLFLOW_ENABLE_SECURE_MODEL_LOADING', 'true').lower() != 'false'
|
834
|
+
|
835
|
+
if use_secure_loading:
|
836
|
+
# Use secure loading for enhanced security
|
837
|
+
from mlflow.utils.secure_loading import SecureModelLoader, SecurityError
|
838
|
+
|
839
|
+
# For compressed files, we need to decompress first then load securely
|
840
|
+
if compression and compression != "none":
|
841
|
+
import tempfile
|
842
|
+
file_open = _COMPRESSION_INFO.get(compression, {}).get("open", open)
|
843
|
+
with file_open(path, "rb") as compressed_f:
|
844
|
+
with tempfile.NamedTemporaryFile(delete=False) as temp_f:
|
845
|
+
temp_f.write(compressed_f.read())
|
846
|
+
temp_path = temp_f.name
|
847
|
+
try:
|
848
|
+
return SecureModelLoader.safe_cloudpickle_load(temp_path)
|
849
|
+
finally:
|
850
|
+
os.unlink(temp_path)
|
851
|
+
else:
|
852
|
+
# Direct secure loading for uncompressed files
|
853
|
+
return SecureModelLoader.safe_cloudpickle_load(path)
|
840
854
|
else:
|
841
|
-
#
|
842
|
-
|
855
|
+
# Use standard cloudpickle loading (original MLflow behavior)
|
856
|
+
# Warning: This bypasses security checks and may allow arbitrary code execution
|
857
|
+
import logging
|
858
|
+
logger = logging.getLogger(__name__)
|
859
|
+
logger.warning(
|
860
|
+
"Secure model loading is disabled. Models will be loaded without security checks. "
|
861
|
+
"This may allow arbitrary code execution. Set MLFLOW_ENABLE_SECURE_MODEL_LOADING=true "
|
862
|
+
"to enable secure loading."
|
863
|
+
)
|
864
|
+
|
865
|
+
file_open = _COMPRESSION_INFO.get(compression, {}).get("open", open)
|
866
|
+
with file_open(path, "rb") as f:
|
867
|
+
return cloudpickle.load(f)
|
843
868
|
|
844
869
|
|
845
870
|
if IS_PYDANTIC_V2_OR_NEWER:
|
mlflow/utils/secure_loading.py
CHANGED
@@ -46,7 +46,7 @@ SAFE_PICKLE_CLASSES = {
|
|
46
46
|
# Built-in types
|
47
47
|
'builtins.dict', 'builtins.list', 'builtins.tuple', 'builtins.set',
|
48
48
|
'builtins.str', 'builtins.int', 'builtins.float', 'builtins.bool',
|
49
|
-
'builtins.type',
|
49
|
+
'builtins.type', 'builtins.object',
|
50
50
|
|
51
51
|
# Collections
|
52
52
|
'collections.OrderedDict',
|
@@ -67,6 +67,14 @@ SAFE_PICKLE_CLASSES = {
|
|
67
67
|
'cloudpickle.cloudpickle._make_empty_cell',
|
68
68
|
'cloudpickle.cloudpickle._make_cell',
|
69
69
|
'cloudpickle.cloudpickle.subimport',
|
70
|
+
'cloudpickle.cloudpickle_fast._class_setstate',
|
71
|
+
'cloudpickle.cloudpickle_fast._function_setstate',
|
72
|
+
'cloudpickle.cloudpickle_fast._builtin_type',
|
73
|
+
'cloudpickle.cloudpickle_fast._make_skeleton_class',
|
74
|
+
'cloudpickle.cloudpickle_fast._make_function',
|
75
|
+
'cloudpickle.cloudpickle_fast._make_empty_cell',
|
76
|
+
'cloudpickle.cloudpickle_fast._make_cell',
|
77
|
+
'cloudpickle.cloudpickle_fast.subimport',
|
70
78
|
|
71
79
|
# Sentence Transformers
|
72
80
|
'sentence_transformers.SentenceTransformer.SentenceTransformer',
|
@@ -113,6 +121,44 @@ SAFE_PICKLE_CLASSES = {
|
|
113
121
|
'model.load_checkpoint',
|
114
122
|
'torch.device',
|
115
123
|
'model.SepClassifier',
|
124
|
+
|
125
|
+
# Generic model module classes (commonly used in custom ML models)
|
126
|
+
# These are general enough to be safe but specific to model loading
|
127
|
+
'model.Model',
|
128
|
+
'model.BaseModel',
|
129
|
+
'model.PythonModel',
|
130
|
+
'model.MLModel',
|
131
|
+
'model.NeuralNetwork',
|
132
|
+
'model.Classifier',
|
133
|
+
'model.Regressor',
|
134
|
+
'model.Predictor',
|
135
|
+
'model.Estimator',
|
136
|
+
'model.Pipeline',
|
137
|
+
'model.Transformer',
|
138
|
+
'model.Encoder',
|
139
|
+
'model.Decoder',
|
140
|
+
'model.Generator',
|
141
|
+
'model.Discriminator',
|
142
|
+
'model.load_model',
|
143
|
+
'model.save_model',
|
144
|
+
'model.predict',
|
145
|
+
'model.transform',
|
146
|
+
'model.fit',
|
147
|
+
'model.evaluate',
|
148
|
+
'model.train',
|
149
|
+
'model.inference',
|
150
|
+
'model.forward',
|
151
|
+
'model.backward',
|
152
|
+
|
153
|
+
# Additional model-related common class names
|
154
|
+
'model.ModelConfig',
|
155
|
+
'model.ModelWrapper',
|
156
|
+
'model.ModelFactory',
|
157
|
+
'model.ModelRegistry',
|
158
|
+
'model.ModelLoader',
|
159
|
+
'model.ModelState',
|
160
|
+
'model.ModelCheckpoint',
|
161
|
+
'model.ModelArtifact',
|
116
162
|
}
|
117
163
|
|
118
164
|
|
@@ -154,11 +200,14 @@ class RestrictedUnpickler(pickle.Unpickler):
|
|
154
200
|
'numpy': ['ndarray', 'dtype', 'int32', 'int64', 'float32', 'float64', 'bool_'],
|
155
201
|
'pandas': ['DataFrame', 'Series', 'Index'],
|
156
202
|
'builtins': ['dict', 'list', 'tuple', 'set', 'str', 'int', 'float', 'bool'],
|
203
|
+
'model': ['*'], # Allow all classes from 'model' module for custom models
|
157
204
|
}
|
158
205
|
|
159
|
-
if module in safe_modules
|
160
|
-
|
161
|
-
|
206
|
+
if module in safe_modules:
|
207
|
+
# Check if all classes are allowed ('*') or if specific class is in list
|
208
|
+
if safe_modules[module] == ['*'] or name in safe_modules[module]:
|
209
|
+
logger.debug(f"Loading safe module class: {full_name}")
|
210
|
+
return super().find_class(module, name)
|
162
211
|
|
163
212
|
# Log and block unsafe class
|
164
213
|
logger.warning(f"Blocked potentially unsafe class: {full_name}")
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|