@@ -94,6 +94,9 @@ def _validate_multi_segment_value(val: str) -> bool:
9494 bool: True if the value is valid and does not violate traversal boundaries,
9595 False otherwise.
9696 """
97+ if val in ('' , '.' , '..' ):
98+ return False
99+
97100 segments = val .split ("/" )
98101 leftover_segments = 0
99102 unseen_segments = len (segments )
@@ -210,40 +213,33 @@ def _extract_and_validate_wildcards(
210213 f"Invalid value { val } for { property_name or 'positional variable' } ."
211214 )
212215
213- # Single-segment templates (None or "*") cannot match exactly "." or ".."
214- # and cannot have multi-segment paths resolving to 0 segments.
215216 if template_str is None or template_str == "*" :
216- if val in ("." , ".." ) or (val and not _validate_multi_segment_value (val )):
217+ # Single-segment templates (None or "*") cannot match exactly "." or ".."
218+ # and cannot have multi-segment paths resolving to 0 segments.
219+ if val and not _validate_multi_segment_value (val ):
217220 raise err
218- return
219-
220- # Multi-segment templates ("**") must represent at least one valid, non-escaped segment.
221- if template_str == "**" :
221+ elif template_str == "**" :
222+ # Multi-segment templates ("**") must represent at least one valid,
223+ # non-escaped segment.
222224 if not _validate_multi_segment_value (val ):
223225 raise err
224- return
225-
226- # Compile the sub-template into a regex capture pattern
227- # to isolate and validate individual wildcard values.
228- pattern , wildcard_types = _build_capture_pattern (template_str )
229-
230- m = pattern .fullmatch (val )
231- if m is not None :
232- # Validate each wildcard value within its matched boundaries,
233- # preventing traversals from escaping their structural positions.
234- for i , wildcard_type in enumerate (wildcard_types ):
235- captured_val = m .group (i + 1 )
236- if wildcard_type == "*" :
237- if captured_val in ("." , ".." ):
238- raise err
239- else :
226+ else :
227+ # Compile the sub-template into a regex capture pattern
228+ # to isolate and validate individual wildcard values.
229+ pattern , wildcard_types = _build_capture_pattern (template_str )
230+
231+ m = pattern .fullmatch (val )
232+ if m is not None :
233+ # Validate each wildcard value within its matched boundaries,
234+ # preventing traversals from escaping their structural positions.
235+ for captured_val in m .groups ():
240236 if not _validate_multi_segment_value (captured_val ):
241237 raise err
242- else :
243- # For values that don't match the pattern, ensure the value doesn't
244- # resolve to 0 segments (e.g. "projects/..").
245- if val and not _validate_multi_segment_value (val ):
246- raise err
238+ else :
239+ # For values that don't match the pattern, ensure the value doesn't
240+ # resolve to 0 segments (e.g. "projects/..").
241+ if val and not _validate_multi_segment_value (val ):
242+ raise err
247243
248244
249245def _expand_variable_match (positional_vars , named_vars , match ):
0 commit comments