flock-core 0.3.5__py3-none-any.whl → 0.3.6__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.

Potentially problematic release.


This version of flock-core might be problematic. Click here for more details.

@@ -7,7 +7,7 @@ from opentelemetry import trace
7
7
 
8
8
  from flock.core.context.context_vars import FLOCK_LAST_AGENT, FLOCK_LAST_RESULT
9
9
  from flock.core.logging.logging import get_logger
10
- from flock.core.util.serializable import Serializable
10
+ from flock.core.serialization.serializable import Serializable
11
11
 
12
12
  logger = get_logger("context")
13
13
  tracer = trace.get_tracer(__name__)
@@ -0,0 +1,175 @@
1
+ import cloudpickle
2
+
3
+
4
+ class SecureSerializer:
5
+ """Security-focused serialization system with capability controls for Flock objects."""
6
+
7
+ # Define capability levels for different modules
8
+ MODULE_CAPABILITIES = {
9
+ # Core Python - unrestricted
10
+ "builtins": "unrestricted",
11
+ "datetime": "unrestricted",
12
+ "re": "unrestricted",
13
+ "math": "unrestricted",
14
+ "json": "unrestricted",
15
+ # Framework modules - unrestricted
16
+ "flock": "unrestricted",
17
+ # System modules - restricted but allowed
18
+ "os": "restricted",
19
+ "io": "restricted",
20
+ "sys": "restricted",
21
+ "subprocess": "high_risk",
22
+ # Network modules - high risk
23
+ "socket": "high_risk",
24
+ "requests": "high_risk",
25
+ }
26
+
27
+ # Functions that should never be serialized
28
+ BLOCKED_FUNCTIONS = {
29
+ "os.system",
30
+ "os.popen",
31
+ "os.spawn",
32
+ "os.exec",
33
+ "subprocess.call",
34
+ "subprocess.run",
35
+ "subprocess.Popen",
36
+ "eval",
37
+ "exec",
38
+ "__import__",
39
+ }
40
+
41
+ @staticmethod
42
+ def _get_module_capability(module_name):
43
+ """Get the capability level for a module."""
44
+ for prefix, level in SecureSerializer.MODULE_CAPABILITIES.items():
45
+ if module_name == prefix or module_name.startswith(f"{prefix}."):
46
+ return level
47
+ return "unknown" # Default to unknown for unlisted modules
48
+
49
+ @staticmethod
50
+ def _is_safe_callable(obj):
51
+ """Check if a callable is safe to serialize."""
52
+ if not callable(obj) or isinstance(obj, type):
53
+ return True, "Not a callable function"
54
+
55
+ module = obj.__module__
56
+ func_name = (
57
+ f"{module}.{obj.__name__}"
58
+ if hasattr(obj, "__name__")
59
+ else "unknown"
60
+ )
61
+
62
+ # Check against blocked functions
63
+ if func_name in SecureSerializer.BLOCKED_FUNCTIONS:
64
+ return False, f"Function {func_name} is explicitly blocked"
65
+
66
+ # Check module capability level
67
+ capability = SecureSerializer._get_module_capability(module)
68
+ if capability == "unknown":
69
+ return False, f"Module {module} has unknown security capability"
70
+
71
+ return True, capability
72
+
73
+ @staticmethod
74
+ def serialize(obj, allow_restricted=True, allow_high_risk=False):
75
+ """Serialize an object with capability checks."""
76
+ if callable(obj) and not isinstance(obj, type):
77
+ is_safe, capability = SecureSerializer._is_safe_callable(obj)
78
+
79
+ if not is_safe:
80
+ raise ValueError(
81
+ f"Cannot serialize unsafe callable: {capability}"
82
+ )
83
+
84
+ if capability == "high_risk" and not allow_high_risk:
85
+ raise ValueError(
86
+ f"High risk callable {obj.__module__}.{obj.__name__} requires explicit permission"
87
+ )
88
+
89
+ if capability == "restricted" and not allow_restricted:
90
+ raise ValueError(
91
+ f"Restricted callable {obj.__module__}.{obj.__name__} requires explicit permission"
92
+ )
93
+
94
+ # Store metadata about the callable for verification during deserialization
95
+ metadata = {
96
+ "module": obj.__module__,
97
+ "name": getattr(obj, "__name__", "unknown"),
98
+ "capability": capability,
99
+ }
100
+
101
+ return {
102
+ "__serialized_callable__": True,
103
+ "data": cloudpickle.dumps(obj).hex(),
104
+ "metadata": metadata,
105
+ }
106
+
107
+ if isinstance(obj, list):
108
+ return [
109
+ SecureSerializer.serialize(
110
+ item, allow_restricted, allow_high_risk
111
+ )
112
+ for item in obj
113
+ ]
114
+
115
+ if isinstance(obj, dict):
116
+ return {
117
+ k: SecureSerializer.serialize(
118
+ v, allow_restricted, allow_high_risk
119
+ )
120
+ for k, v in obj.items()
121
+ }
122
+
123
+ return obj
124
+
125
+ @staticmethod
126
+ def deserialize(obj, allow_restricted=True, allow_high_risk=False):
127
+ """Deserialize an object with capability enforcement."""
128
+ if isinstance(obj, dict) and obj.get("__serialized_callable__") is True:
129
+ # Validate the capability level during deserialization
130
+ metadata = obj.get("metadata", {})
131
+ capability = metadata.get("capability", "unknown")
132
+
133
+ if capability == "high_risk" and not allow_high_risk:
134
+ raise ValueError(
135
+ f"Cannot deserialize high risk callable {metadata.get('module')}.{metadata.get('name')}"
136
+ )
137
+
138
+ if capability == "restricted" and not allow_restricted:
139
+ raise ValueError(
140
+ f"Cannot deserialize restricted callable {metadata.get('module')}.{metadata.get('name')}"
141
+ )
142
+
143
+ try:
144
+ callable_obj = cloudpickle.loads(bytes.fromhex(obj["data"]))
145
+
146
+ # Additional verification that the deserialized object matches its metadata
147
+ if callable_obj.__module__ != metadata.get("module") or (
148
+ hasattr(callable_obj, "__name__")
149
+ and callable_obj.__name__ != metadata.get("name")
150
+ ):
151
+ raise ValueError(
152
+ "Callable metadata mismatch - possible tampering detected"
153
+ )
154
+
155
+ return callable_obj
156
+ except Exception as e:
157
+ raise ValueError(f"Failed to deserialize callable: {e!s}")
158
+
159
+ if isinstance(obj, list):
160
+ return [
161
+ SecureSerializer.deserialize(
162
+ item, allow_restricted, allow_high_risk
163
+ )
164
+ for item in obj
165
+ ]
166
+
167
+ if isinstance(obj, dict) and "__serialized_callable__" not in obj:
168
+ return {
169
+ k: SecureSerializer.deserialize(
170
+ v, allow_restricted, allow_high_risk
171
+ )
172
+ for k, v in obj.items()
173
+ }
174
+
175
+ return obj
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flock-core
3
- Version: 0.3.5
3
+ Version: 0.3.6
4
4
  Summary: Declarative LLM Orchestration at Scale
5
5
  Author-email: Andre Ratzenberger <andre.ratzenberger@whiteduck.de>
6
6
  License-File: LICENSE
@@ -16,7 +16,7 @@ flock/core/flock_api.py,sha256=SKQVKgFCaNCqHtwvIcksnpqG6ajHodVhs3oaKUw-d8c,7192
16
16
  flock/core/flock_evaluator.py,sha256=j7riJj_KsWoBnKmLiGp-U0CRhxDyJbgEdLGN26tfKm8,1588
17
17
  flock/core/flock_factory.py,sha256=vyDq0eyFT4MyE_n2JyNU7YaFx2ljmjSDmZ07OIsmIOE,2694
18
18
  flock/core/flock_module.py,sha256=VWFlBiY2RHZLTlGYfcchuT41M3m_JrZcmzw07u7KayM,2581
19
- flock/core/context/context.py,sha256=fb7SsGAXmhQ1CvHV3_GihGiJG-4oLJ_DcexJ8vsrbHM,6371
19
+ flock/core/context/context.py,sha256=AW0qKIAkgZucVroGsulrPVPc4WmWuqWIrVPHf2qaOLI,6380
20
20
  flock/core/context/context_manager.py,sha256=qMySVny_dbTNLh21RHK_YT0mNKIOrqJDZpi9ZVdBsxU,1103
21
21
  flock/core/context/context_vars.py,sha256=0Hn6fM2iNc0_jIIU0B7KX-K2o8qXqtZ5EYtwujETQ7U,272
22
22
  flock/core/execution/local_executor.py,sha256=rnIQvaJOs6zZORUcR3vvyS6LPREDJTjaygl_Db0M8ao,952
@@ -37,12 +37,13 @@ flock/core/logging/telemetry_exporter/sqlite_exporter.py,sha256=CDsiMb9QcqeXelZ6
37
37
  flock/core/mixin/dspy_integration.py,sha256=P5G4Y04nl5hFwFbJXCkQ-0TMR1L4skLL2IM_FlUjH_c,8364
38
38
  flock/core/mixin/prompt_parser.py,sha256=eOqI-FK3y17gVqpc_y5GF-WmK1Jv8mFlkZxTcgweoxI,5121
39
39
  flock/core/registry/agent_registry.py,sha256=TUClh9e3eA6YzZC1CMTlsTPvQeqb9jYHewi-zPpcWM8,4987
40
+ flock/core/serialization/secure_serializer.py,sha256=n5-zRvvXddgJv1FFHsaQ2wuYdL3WUSGPvG_LGaffEJo,6144
41
+ flock/core/serialization/serializable.py,sha256=SymJ0YrjBx48mOBItYSqoRpKuzIc4vKWRS6ScTzre7s,2573
40
42
  flock/core/tools/basic_tools.py,sha256=fI9r81_ktRiRhNLwT-jSJ9rkjl28LC1ZfL-njnno2iw,4761
41
43
  flock/core/tools/dev_tools/github.py,sha256=a2OTPXS7kWOVA4zrZHynQDcsmEi4Pac5MfSjQOLePzA,5308
42
44
  flock/core/util/cli_helper.py,sha256=IOl9r4cz_MJv_Bp5R8dhHX8f-unAqA9vDS6-0E90Vzk,49813
43
45
  flock/core/util/hydrator.py,sha256=6qNwOwCZB7r6y25BZ--0PGofrAlfMaXbDKFQeP5NLts,11196
44
46
  flock/core/util/input_resolver.py,sha256=g9vDPdY4OH-G7qjas5ksGEHueokHGFPMoLOvC-ngeLo,5984
45
- flock/core/util/serializable.py,sha256=SymJ0YrjBx48mOBItYSqoRpKuzIc4vKWRS6ScTzre7s,2573
46
47
  flock/evaluators/declarative/declarative_evaluator.py,sha256=f8ldgZZp94zC4CoGzBufKvbvtckCGBe9EHTOoAZfZK0,1695
47
48
  flock/evaluators/natural_language/natural_language_evaluator.py,sha256=6nVEeh8_uwv_h-d3FWlA0GbzDzRtdhvxCGKirHtyvOU,2012
48
49
  flock/evaluators/zep/zep_evaluator.py,sha256=hEHQdgIwGsbC4ci9RvtdA2k7f4M0yznIok4v4XltNwg,1885
@@ -396,8 +397,8 @@ flock/workflow/activities.py,sha256=2zcYyDoCuYs9oQbnhLjCzBUdEi7d5IEIemKJ7TV_B8w,
396
397
  flock/workflow/agent_activities.py,sha256=NhBZscflEf2IMfSRa_pBM_TRP7uVEF_O0ROvWZ33eDc,963
397
398
  flock/workflow/temporal_setup.py,sha256=VWBgmBgfTBjwM5ruS_dVpA5AVxx6EZ7oFPGw4j3m0l0,1091
398
399
  flock/workflow/workflow.py,sha256=I9MryXW_bqYVTHx-nl2epbTqeRy27CAWHHA7ZZA0nAk,1696
399
- flock_core-0.3.5.dist-info/METADATA,sha256=MBhu8EjW-aFe1MCkusE0AiL4tE7Pv6kdh1czCCbqVLU,20494
400
- flock_core-0.3.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
401
- flock_core-0.3.5.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
402
- flock_core-0.3.5.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
403
- flock_core-0.3.5.dist-info/RECORD,,
400
+ flock_core-0.3.6.dist-info/METADATA,sha256=-TPh-D8HF2et5uEyksY7uwhl9Fgc0b_RRf0PMe1B2hg,20494
401
+ flock_core-0.3.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
402
+ flock_core-0.3.6.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
403
+ flock_core-0.3.6.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
404
+ flock_core-0.3.6.dist-info/RECORD,,
File without changes