1818from enum import Enum
1919from typing import Any
2020
21- from pydantic import BaseModel , Field
21+ from pydantic import BaseModel , Field , field_validator
2222
2323from graphiti_core .driver .driver import GraphProvider
24+ from graphiti_core .helpers import validate_node_labels
2425
2526
2627class ComparisonOperator (Enum ):
@@ -65,6 +66,12 @@ class SearchFilters(BaseModel):
6566 edge_uuids : list [str ] | None = Field (default = None )
6667 property_filters : list [PropertyFilter ] | None = Field (default = None )
6768
69+ @field_validator ('node_labels' )
70+ @classmethod
71+ def validate_node_label_filters (cls , value : list [str ] | None ) -> list [str ] | None :
72+ validate_node_labels (value )
73+ return value
74+
6875
6976def cypher_to_opensearch_operator (op : ComparisonOperator ) -> str :
7077 mapping = {
@@ -84,6 +91,8 @@ def node_search_filter_query_constructor(
8491 filter_params : dict [str , Any ] = {}
8592
8693 if filters .node_labels is not None :
94+ # Defense-in-depth for model_construct()/other validation bypasses.
95+ validate_node_labels (filters .node_labels )
8796 if provider == GraphProvider .KUZU :
8897 node_label_filter = 'list_has_all(n.labels, $labels)'
8998 filter_params ['labels' ] = filters .node_labels
@@ -125,6 +134,8 @@ def edge_search_filter_query_constructor(
125134 filter_params ['edge_uuids' ] = filters .edge_uuids
126135
127136 if filters .node_labels is not None :
137+ # Defense-in-depth for model_construct()/other validation bypasses.
138+ validate_node_labels (filters .node_labels )
128139 if provider == GraphProvider .KUZU :
129140 node_label_filter = (
130141 'list_has_all(n.labels, $labels) AND list_has_all(m.labels, $labels)'
0 commit comments