Skip to content

Commit d6d4f3b

Browse files
Python: refinement of filtering (microsoft#13505)
### Motivation and Context <!-- Thank you for your contribution to the semantic-kernel repo! Please help reviewers and future users, providing the following information: 1. Why is this change required? 2. What problem does it solve? 3. What scenario does it contribute to? 4. If it fixes an open issue, please link to the issue here. --> further refinement of in memory filtering ### Description <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I didn't break anyone 😄
1 parent c4d0a62 commit d6d4f3b

1 file changed

Lines changed: 64 additions & 0 deletions

File tree

‎python/semantic_kernel/connectors/in_memory.py‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,63 @@ class InMemoryCollection(
166166
"items",
167167
}
168168

169+
# Blocklist of dangerous attribute names that cannot be accessed in filter expressions.
170+
# These attributes can be used to escape the sandbox and execute arbitrary code.
171+
blocked_filter_attributes: ClassVar[set[str]] = {
172+
# Object introspection - can lead to class/module access
173+
"__class__",
174+
"__bases__",
175+
"__mro__",
176+
"__subclasses__",
177+
# Code and function internals
178+
"__code__",
179+
"__globals__",
180+
"__closure__",
181+
"__func__",
182+
"__self__",
183+
"__dict__",
184+
"__slots__",
185+
# Attribute access hooks
186+
"__getattr__",
187+
"__getattribute__",
188+
"__setattr__",
189+
"__delattr__",
190+
# Import and builtins
191+
"__builtins__",
192+
"__import__",
193+
"__loader__",
194+
"__spec__",
195+
# Module attributes
196+
"__name__",
197+
"__qualname__",
198+
"__module__",
199+
"__file__",
200+
"__path__",
201+
"__package__",
202+
# Descriptor protocol
203+
"__get__",
204+
"__set__",
205+
"__delete__",
206+
# Metaclass and creation
207+
"__new__",
208+
"__init__",
209+
"__init_subclass__",
210+
"__prepare__",
211+
"__call__",
212+
# Other dangerous attributes
213+
"__reduce__",
214+
"__reduce_ex__",
215+
"__getstate__",
216+
"__setstate__",
217+
"func_globals", # Python 2 compatibility name
218+
"gi_frame", # Generator frame access
219+
"gi_code",
220+
"f_globals", # Frame globals
221+
"f_locals",
222+
"f_builtins",
223+
"co_consts", # Code object constants
224+
}
225+
169226
def __init__(
170227
self,
171228
record_type: type[TModel],
@@ -358,6 +415,13 @@ def _parse_and_validate_filter(self, filter_str: str) -> Callable:
358415
f"AST node type '{node_type.__name__}' is not allowed in filter expressions."
359416
)
360417

418+
# For Attribute nodes, validate that dangerous dunder attributes are not accessed
419+
if isinstance(node, ast.Attribute) and node.attr in self.blocked_filter_attributes:
420+
raise VectorStoreOperationException(
421+
f"Access to attribute '{node.attr}' is not allowed in filter expressions. "
422+
"This attribute could be used to escape the filter sandbox."
423+
)
424+
361425
# For Name nodes, only allow the lambda parameter
362426
if isinstance(node, ast.Name) and node.id not in lambda_param_names:
363427
raise VectorStoreOperationException(

0 commit comments

Comments
 (0)