genesis-flow 1.0.7__py3-none-any.whl → 1.0.9__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: genesis-flow
3
- Version: 1.0.7
3
+ Version: 1.0.9
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.
@@ -316,7 +316,6 @@ Genesis-Flow is a secure, lightweight, and scalable ML operations platform built
316
316
 
317
317
  ### Security-First Design
318
318
  - **Input validation** against SQL injection and path traversal attacks
319
- - **Secure model loading** with restricted pickle deserialization
320
319
  - **Authentication** and authorization ready for enterprise deployment
321
320
  - **Security patches** for all known vulnerabilities in dependencies
322
321
 
@@ -504,7 +503,6 @@ export MLFLOW_POSTGRES_USERNAME="user@tenant"
504
503
  export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
505
504
 
506
505
  # Security configuration
507
- export MLFLOW_ENABLE_SECURE_MODEL_LOADING=true
508
506
  export MLFLOW_STRICT_INPUT_VALIDATION=true
509
507
  ```
510
508
 
@@ -761,7 +759,6 @@ entry_points = {
761
759
 
762
760
  - ✅ **Input validation** against injection attacks
763
761
  - ✅ **Path traversal protection** for file operations
764
- - ✅ **Secure pickle loading** with restricted unpickling
765
762
  - ✅ **Authentication hooks** for enterprise SSO integration
766
763
  - ✅ **Audit logging** for compliance requirements
767
764
  - ✅ **Encrypted communication** support
@@ -1,4 +1,4 @@
1
- genesis_flow-1.0.7.dist-info/licenses/LICENSE.txt,sha256=Y5U1Xebzka__NZlqMPtBsYm0mRpMtUmTrONatpoL-ig,11382
1
+ genesis_flow-1.0.9.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=aDwfNKgoVw4sl9W0WZfOa9st5WTsSF3NWbF5TgM3bDs,64507
314
+ mlflow/pyfunc/model.py,sha256=sOM5lgC0cvZmbv-u-NVE4xwWKv6WskP_xR8YKVNvOIg,63797
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
@@ -364,7 +364,7 @@ mlflow/server/graphql/graphql_errors.py,sha256=B-U26g2vsJoKNg2hax-Gl3A66LB-y5adB
364
364
  mlflow/server/graphql/graphql_no_batching.py,sha256=3J7h6-qn6nbonYZWWCBlOgMC37NiSnKvA6P_rp5sSxc,2972
365
365
  mlflow/server/graphql/graphql_schema_extensions.py,sha256=i6DeNbzLcvBKXc_jLG_dCdXwA2cY__XPM6bU1dGQ8bM,2329
366
366
  mlflow/shap/__init__.py,sha256=i6UAJd-XYu7Nw6rbfxaGvr5vfK-6gUfU2MXMAZvSM-c,25558
367
- mlflow/sklearn/__init__.py,sha256=ovyR0zHB_HKoysOlElzx2EsonkisucHR8PslBsVMtfA,86026
367
+ mlflow/sklearn/__init__.py,sha256=unYCnl3rXRlwptsluRiLjooR_KBM6anOZrvbzgiKe1A,85957
368
368
  mlflow/sklearn/utils.py,sha256=CM9z-UD65RBN4sIdEoJWhazkdmE9Wa9InjsU61y1XfE,38912
369
369
  mlflow/smolagents/__init__.py,sha256=V2sfkuWxQ090CaIjwBh7icD0bSgYP3jKD5MRzy__uW0,2202
370
370
  mlflow/smolagents/autolog.py,sha256=5GJpqmXs8dd2tf4jkL6fk7Fxb0TsxAMykB865M-BpK8,4770
@@ -613,7 +613,6 @@ 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=1d-Hf0QkU6WkGjLKvAKcXv7sLa6xl2utig1lT-Hhyp4,10262
617
616
  mlflow/utils/security_validation.py,sha256=cLBrLNOoVJuAffO677v0m_v4i-01v7aLk-sJk87mpkQ,12830
618
617
  mlflow/utils/server_cli_utils.py,sha256=gbT5CVkOLorSw-y8bnNSBEP9mClcVTagtTN5SK5Azhw,2381
619
618
  mlflow/utils/spark_utils.py,sha256=zUbQIRAtwyU3rDJK8m7v42KO2TSGn28Coe_UYBEhIWA,395
@@ -641,8 +640,8 @@ mlflow/utils/autologging_utils/metrics_queue.py,sha256=bwpMX7Go6xFxrpYROi6rDBdVt
641
640
  mlflow/utils/autologging_utils/safety.py,sha256=IwbTbusyE87Hc4qkhhvMikoaZqX9kpr972FWS2B8goc,51465
642
641
  mlflow/utils/autologging_utils/versioning.py,sha256=2hSN4KXFWEJCcopDdLG6BiPeqSoqjETeNMuUBsCCwlI,3762
643
642
  mlflow/utils/import_hooks/__init__.py,sha256=werje98Woelkbwrhtlb8wmRdt3RtiL--LqGru7Xh3YU,13589
644
- genesis_flow-1.0.7.dist-info/METADATA,sha256=Z4t8Zn9OIxkH7d-hTozfYP0c8_-VB-WQ0KWo8XxyDHw,33401
645
- genesis_flow-1.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
646
- genesis_flow-1.0.7.dist-info/entry_points.txt,sha256=YZZiTHSYQpv8vou6gdqWI17piK9Pm0P3BmZ-xepUtnw,449
647
- genesis_flow-1.0.7.dist-info/top_level.txt,sha256=wm8UqYyUHI21EvrTDHb3eYICy0dOVDLBhAL-jp5zbuI,7
648
- genesis_flow-1.0.7.dist-info/RECORD,,
643
+ genesis_flow-1.0.9.dist-info/METADATA,sha256=yiOvGLekYICCUhdHRvUEjtFrmOoFYZ2xNn2wzXkSS2w,33229
644
+ genesis_flow-1.0.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
645
+ genesis_flow-1.0.9.dist-info/entry_points.txt,sha256=YZZiTHSYQpv8vou6gdqWI17piK9Pm0P3BmZ-xepUtnw,449
646
+ genesis_flow-1.0.9.dist-info/top_level.txt,sha256=wm8UqYyUHI21EvrTDHb3eYICy0dOVDLBhAL-jp5zbuI,7
647
+ genesis_flow-1.0.9.dist-info/RECORD,,
mlflow/pyfunc/model.py CHANGED
@@ -818,28 +818,10 @@ def _maybe_compress_cloudpickle_dump(python_model, path, compression):
818
818
 
819
819
 
820
820
  def _maybe_decompress_cloudpickle_load(path, compression):
821
- """
822
- Genesis-Flow: Secure model loading with safety checks.
823
- """
824
- from mlflow.utils.secure_loading import SecureModelLoader, SecurityError
825
-
826
821
  _check_compression_supported(compression)
827
-
828
- # For compressed files, we need to decompress first then load securely
829
- if compression and compression != "none":
830
- import tempfile
831
- file_open = _COMPRESSION_INFO.get(compression, {}).get("open", open)
832
- with file_open(path, "rb") as compressed_f:
833
- with tempfile.NamedTemporaryFile(delete=False) as temp_f:
834
- temp_f.write(compressed_f.read())
835
- temp_path = temp_f.name
836
- try:
837
- return SecureModelLoader.safe_cloudpickle_load(temp_path)
838
- finally:
839
- os.unlink(temp_path)
840
- else:
841
- # Direct secure loading for uncompressed files
842
- return SecureModelLoader.safe_cloudpickle_load(path)
822
+ file_open = _COMPRESSION_INFO.get(compression, {}).get("open", open)
823
+ with file_open(path, "rb") as f:
824
+ return cloudpickle.load(f)
843
825
 
844
826
 
845
827
  if IS_PYDANTIC_V2_OR_NEWER:
@@ -465,13 +465,14 @@ def _load_model_from_local_file(path, serialization_format):
465
465
  ),
466
466
  error_code=INVALID_PARAMETER_VALUE,
467
467
  )
468
- # Genesis-Flow: Use secure model loading to prevent code execution attacks
469
- from mlflow.utils.secure_loading import SecureModelLoader
470
-
471
468
  if serialization_format == SERIALIZATION_FORMAT_PICKLE:
472
- return SecureModelLoader.safe_pickle_load(path)
469
+ import pickle
470
+ with open(path, "rb") as f:
471
+ return pickle.load(f)
473
472
  elif serialization_format == SERIALIZATION_FORMAT_CLOUDPICKLE:
474
- return SecureModelLoader.safe_cloudpickle_load(path)
473
+ import cloudpickle
474
+ with open(path, "rb") as f:
475
+ return cloudpickle.load(f)
475
476
 
476
477
 
477
478
  def _load_pyfunc(path):
@@ -1,285 +0,0 @@
1
- """
2
- Genesis-Flow Secure Model Loading
3
-
4
- This module provides secure alternatives to pickle-based model loading,
5
- addressing security vulnerabilities in model deserialization.
6
- """
7
-
8
- import io
9
- import pickle
10
- import cloudpickle
11
- import logging
12
- import hashlib
13
- from typing import Any, Set, Optional, Union, Type
14
- from pathlib import Path
15
-
16
- logger = logging.getLogger(__name__)
17
-
18
- # Allowlist of safe classes that can be unpickled
19
- SAFE_PICKLE_CLASSES = {
20
-
21
- # STD types
22
- 'time.time',
23
-
24
- # NumPy types
25
- 'numpy.ndarray',
26
- 'numpy.dtype',
27
- 'numpy.int32', 'numpy.int64', 'numpy.float32', 'numpy.float64',
28
- 'numpy.bool_', 'numpy.str_',
29
-
30
- # Pandas types
31
- 'pandas.core.frame.DataFrame',
32
- 'pandas.core.series.Series',
33
- 'pandas.core.index.Index',
34
- 'pandas.core.dtypes.dtypes.CategoricalDtype',
35
-
36
- # Scikit-learn estimators
37
- 'sklearn.linear_model._base.LinearRegression',
38
- 'sklearn.linear_model._logistic.LogisticRegression',
39
- 'sklearn.ensemble._forest.RandomForestClassifier',
40
- 'sklearn.ensemble._forest.RandomForestRegressor',
41
- 'sklearn.tree._classes.DecisionTreeClassifier',
42
- 'sklearn.tree._classes.DecisionTreeRegressor',
43
- 'sklearn.svm._classes.SVC',
44
- 'sklearn.svm._classes.SVR',
45
-
46
- # Built-in types
47
- 'builtins.dict', 'builtins.list', 'builtins.tuple', 'builtins.set',
48
- 'builtins.str', 'builtins.int', 'builtins.float', 'builtins.bool',
49
- 'builtins.type',
50
-
51
- # Collections
52
- 'collections.OrderedDict',
53
- 'collections.defaultdict',
54
-
55
- # MLflow types
56
- 'mlflow.models.signature.ModelSignature',
57
- 'mlflow.models.signature._TypeHints',
58
- 'mlflow.types.schema.Schema',
59
- 'mlflow.pyfunc.model.PythonModel',
60
-
61
- # Cloudpickle internals
62
- 'cloudpickle.cloudpickle._make_skeleton_class',
63
- 'cloudpickle.cloudpickle._class_setstate',
64
- 'cloudpickle.cloudpickle._make_function',
65
- 'cloudpickle.cloudpickle._builtin_type',
66
- 'cloudpickle.cloudpickle._function_setstate',
67
- 'cloudpickle.cloudpickle._make_empty_cell',
68
- 'cloudpickle.cloudpickle._make_cell',
69
- 'cloudpickle.cloudpickle.subimport',
70
-
71
- # Sentence Transformers
72
- 'sentence_transformers.SentenceTransformer.SentenceTransformer',
73
- 'sentence_transformers.model_card.SentenceTransformerModelCardData',
74
- 'sentence_transformers.models.Transformer.Transformer',
75
- 'sentence_transformers.models.Pooling.Pooling',
76
- 'sentence_transformers.models.Normalize.Normalize',
77
-
78
- # Torch
79
- 'torch.torch_version.TorchVersion',
80
- 'torch._utils._rebuild_tensor_v2',
81
- 'torch.storage._load_from_bytes',
82
- 'torch.nn.modules.sparse.Embedding',
83
- 'torch._utils._rebuild_parameter',
84
- 'torch.nn.modules.normalization.LayerNorm',
85
- 'torch.nn.modules.dropout.Dropout',
86
- 'torch.nn.modules.container.ModuleList',
87
- 'torch.nn.modules.linear.Linear',
88
- 'torch.nn.modules.activation.Tanh',
89
- 'torch.float32',
90
- 'torch._C._nn.gelu',
91
-
92
- # Transformers
93
- 'transformers.models.bert.modeling_bert.BertModel',
94
- 'transformers.models.bert.modeling_bert.BertEmbeddings',
95
- 'transformers.models.bert.modeling_bert.BertEncoder',
96
- 'transformers.models.bert.modeling_bert.BertLayer',
97
- 'transformers.models.bert.modeling_bert.BertAttention',
98
- 'transformers.models.bert.modeling_bert.BertSdpaSelfAttention',
99
- 'transformers.models.bert.modeling_bert.BertSelfOutput',
100
- 'transformers.models.bert.modeling_bert.BertIntermediate',
101
- 'transformers.models.bert.modeling_bert.BertOutput',
102
- 'transformers.models.bert.modeling_bert.BertPooler',
103
- 'transformers.models.bert.configuration_bert.BertConfig',
104
- 'transformers.models.bert.tokenization_bert_fast.BertTokenizerFast',
105
- 'transformers.activations.GELUActivation',
106
-
107
- # Tokenizers
108
- 'tokenizers.Tokenizer',
109
- 'tokenizers.models.Model',
110
- 'tokenizers.AddedToken',
111
-
112
- # PyTorch
113
- 'model.load_checkpoint',
114
- 'torch.device',
115
- 'model.SepClassifier',
116
- }
117
-
118
-
119
- class RestrictedUnpickler(pickle.Unpickler):
120
- """
121
- Secure unpickler that only allows safe, whitelisted classes.
122
-
123
- This prevents arbitrary code execution during model deserialization
124
- by restricting which classes can be instantiated.
125
- """
126
-
127
- def __init__(self, file, *, safe_classes: Optional[Set[str]] = None):
128
- super().__init__(file)
129
- self.safe_classes = safe_classes or SAFE_PICKLE_CLASSES
130
-
131
- def find_class(self, module: str, name: str) -> Type:
132
- """
133
- Override to restrict class loading to safe classes only.
134
-
135
- Args:
136
- module: Module name
137
- name: Class name
138
-
139
- Returns:
140
- Class object if safe
141
-
142
- Raises:
143
- SecurityError: If class is not in allowlist
144
- """
145
- full_name = f"{module}.{name}"
146
-
147
- # Check if the class is in our safe list
148
- if full_name in self.safe_classes:
149
- logger.debug(f"Loading safe class: {full_name}")
150
- return super().find_class(module, name)
151
-
152
- # Additional check for known safe modules
153
- safe_modules = {
154
- 'numpy': ['ndarray', 'dtype', 'int32', 'int64', 'float32', 'float64', 'bool_'],
155
- 'pandas': ['DataFrame', 'Series', 'Index'],
156
- 'builtins': ['dict', 'list', 'tuple', 'set', 'str', 'int', 'float', 'bool'],
157
- }
158
-
159
- if module in safe_modules and name in safe_modules[module]:
160
- logger.debug(f"Loading safe module class: {full_name}")
161
- return super().find_class(module, name)
162
-
163
- # Log and block unsafe class
164
- logger.warning(f"Blocked potentially unsafe class: {full_name}")
165
- raise pickle.UnpicklingError(
166
- f"Security: Class '{full_name}' is not in the allowlist. "
167
- f"If this is a legitimate model class, add it to SAFE_PICKLE_CLASSES."
168
- )
169
-
170
- class SecureModelLoader:
171
- """
172
- Secure model loading with multiple safety mechanisms.
173
- """
174
-
175
- @staticmethod
176
- def calculate_file_hash(file_path: Union[str, Path]) -> str:
177
- """Calculate SHA256 hash of a file for integrity checking."""
178
- hasher = hashlib.sha256()
179
- with open(file_path, 'rb') as f:
180
- for chunk in iter(lambda: f.read(4096), b""):
181
- hasher.update(chunk)
182
- return hasher.hexdigest()
183
-
184
- @staticmethod
185
- def safe_pickle_load(file_path: Union[str, Path], *, safe_classes: Optional[Set[str]] = None) -> Any:
186
- """
187
- Safely load a pickle file using restricted unpickler.
188
-
189
- Args:
190
- file_path: Path to pickle file
191
- safe_classes: Optional custom set of safe classes
192
-
193
- Returns:
194
- Unpickled object
195
-
196
- Raises:
197
- SecurityError: If file contains unsafe classes
198
- FileNotFoundError: If file doesn't exist
199
- """
200
- file_path = Path(file_path)
201
-
202
- if not file_path.exists():
203
- raise FileNotFoundError(f"Model file not found: {file_path}")
204
-
205
- # Log file hash for audit trail
206
- file_hash = SecureModelLoader.calculate_file_hash(file_path)
207
- logger.info(f"Loading model file {file_path.name} (SHA256: {file_hash[:16]}...)")
208
-
209
- try:
210
- with open(file_path, 'rb') as f:
211
- unpickler = RestrictedUnpickler(f, safe_classes=safe_classes)
212
- model = unpickler.load()
213
- logger.info(f"Successfully loaded model of type: {type(model).__name__}")
214
- return model
215
- except pickle.UnpicklingError as e:
216
- logger.error(f"Security: Unsafe model file rejected: {e}")
217
- raise SecurityError(f"Model file contains unsafe content: {e}") from e
218
- except Exception as e:
219
- logger.error(f"Error loading model: {e}")
220
- raise
221
-
222
- @staticmethod
223
- def safe_cloudpickle_load(file_path: Union[str, Path], *, safe_classes: Optional[Set[str]] = None) -> Any:
224
- """
225
- Safely load a cloudpickle file using restricted unpickler.
226
-
227
- Args:
228
- file_path: Path to cloudpickle file
229
- safe_classes: Optional custom set of safe classes
230
-
231
- Returns:
232
- Unpickled object
233
- """
234
- file_path = Path(file_path)
235
-
236
- if not file_path.exists():
237
- raise FileNotFoundError(f"Model file not found: {file_path}")
238
-
239
- # Calculate file hash for audit trail
240
- file_hash = SecureModelLoader.calculate_file_hash(file_path)
241
- logger.info(f"Loading cloudpickle file {file_path.name} (SHA256: {file_hash[:16]}...)")
242
-
243
- try:
244
- with open(file_path, 'rb') as f:
245
- # Use cloudpickle's load with our custom unpickler
246
- # Note: This is a simplified approach - in practice, cloudpickle's
247
- # load function would need to be modified to accept a custom unpickler
248
- unpickler = RestrictedUnpickler(f, safe_classes=safe_classes)
249
- model = unpickler.load()
250
- logger.info(f"Successfully loaded cloudpickle model of type: {type(model).__name__}")
251
- return model
252
- except pickle.UnpicklingError as e:
253
- logger.error(f"Security: Unsafe cloudpickle file rejected: {e}")
254
- raise SecurityError(f"CloudPickle file contains unsafe content: {e}") from e
255
- except Exception as e:
256
- logger.error(f"Error loading cloudpickle model: {e}")
257
- raise
258
-
259
- class SecurityError(Exception):
260
- """Exception raised for security-related model loading issues."""
261
- pass
262
-
263
- def add_safe_class(class_name: str) -> None:
264
- """
265
- Add a class to the safe loading allowlist.
266
-
267
- Args:
268
- class_name: Full class name (e.g., 'mymodule.MyClass')
269
- """
270
- SAFE_PICKLE_CLASSES.add(class_name)
271
- logger.info(f"Added {class_name} to safe loading allowlist")
272
-
273
- def remove_safe_class(class_name: str) -> None:
274
- """
275
- Remove a class from the safe loading allowlist.
276
-
277
- Args:
278
- class_name: Full class name to remove
279
- """
280
- SAFE_PICKLE_CLASSES.discard(class_name)
281
- logger.info(f"Removed {class_name} from safe loading allowlist")
282
-
283
- def get_safe_classes() -> Set[str]:
284
- """Return a copy of the current safe classes set."""
285
- return SAFE_PICKLE_CLASSES.copy()