@@ -489,8 +489,9 @@ def _safe_extract_tar(tar: tarfile.TarFile, path: str) -> None:
489489 # Manual validation for older Python versions
490490 for member in tar .getmembers ():
491491 # Check the member's target path
492- member_path = os .path .join (path , member .name )
493- if not _is_within_directory (path , member_path ):
492+ try :
493+ safe_path_join (path , member .name )
494+ except ValueError :
494495 raise ValueError (
495496 f"Attempted path traversal in tar file: { member .name } "
496497 )
@@ -500,21 +501,26 @@ def _safe_extract_tar(tar: tarfile.TarFile, path: str) -> None:
500501 # Get the link target (can be absolute or relative)
501502 link_target = member .linkname
502503
503- # If it's a relative symlink, resolve it relative to the member's directory
504+ # If it's a relative symlink, resolve it relative to the member's directory.
505+ # Pass the archive-relative dirname and link target as separate parts to
506+ # safe_path_join, which canonicalises and validates containment in one step.
504507 if not os .path .isabs (link_target ):
505- member_dir = os .path .dirname (member_path )
506- link_target = os .path .join (member_dir , link_target )
508+ try :
509+ safe_path_join (
510+ path , os .path .dirname (member .name ), link_target
511+ )
512+ except ValueError :
513+ raise ValueError (
514+ f"Symlink { member .name } points outside extraction directory: { member .linkname } "
515+ )
507516 else :
508517 # Absolute symlinks are dangerous - make them relative to extraction path
509- link_target = os .path .join (
510- path , link_target .lstrip (os .sep )
511- )
512-
513- # Check if the resolved symlink target is within the directory
514- if not _is_within_directory (path , link_target ):
515- raise ValueError (
516- f"Symlink { member .name } points outside extraction directory: { member .linkname } "
517- )
518+ try :
519+ safe_path_join (path , link_target .lstrip (os .sep ))
520+ except ValueError :
521+ raise ValueError (
522+ f"Symlink { member .name } points outside extraction directory: { member .linkname } "
523+ )
518524
519525 tar .extractall (path = path )
520526
@@ -533,8 +539,9 @@ def _safe_extract_zip(zip_file: zipfile.ZipFile, path: str) -> None:
533539 created by Unix-based archiving tools and may not be portable.
534540 """
535541 for member in zip_file .namelist ():
536- member_path = os .path .join (path , member )
537- if not _is_within_directory (path , member_path ):
542+ try :
543+ safe_path_join (path , member )
544+ except ValueError :
538545 raise ValueError (f"Attempted path traversal in zip file: { member } " )
539546
540547 # Check for potential symlinks in ZIP files
@@ -548,21 +555,26 @@ def _safe_extract_zip(zip_file: zipfile.ZipFile, path: str) -> None:
548555 # Read the symlink target from the file content
549556 link_target = zip_file .read (member ).decode ("utf-8" )
550557
551- # Resolve the link target relative to the member's directory
558+ # Resolve the link target relative to the member's directory.
559+ # Pass the archive-relative dirname and link target as separate parts to
560+ # safe_path_join, which canonicalises and validates containment in one step.
552561 if not os .path .isabs (link_target ):
553- member_dir = os .path .dirname (member_path )
554- resolved_target = os .path .join (member_dir , link_target )
562+ try :
563+ safe_path_join (
564+ path , os .path .dirname (member ), link_target
565+ )
566+ except ValueError :
567+ raise ValueError (
568+ f"Symlink { member } points outside extraction directory: { link_target } "
569+ )
555570 else :
556571 # Absolute symlinks - make them relative to extraction path
557- resolved_target = os .path .join (
558- path , link_target .lstrip (os .sep )
559- )
560-
561- # Check if the symlink target is within the directory
562- if not _is_within_directory (path , resolved_target ):
563- raise ValueError (
564- f"Symlink { member } points outside extraction directory: { link_target } "
565- )
572+ try :
573+ safe_path_join (path , link_target .lstrip (os .sep ))
574+ except ValueError :
575+ raise ValueError (
576+ f"Symlink { member } points outside extraction directory: { link_target } "
577+ )
566578
567579 zip_file .extractall (path = path )
568580
@@ -909,7 +921,7 @@ def get_hf_hub(repo_id: str, filename: str = "") -> str:
909921 raise RuntimeError (f"An unexpected error occurred: { e } " ) from e
910922 hf_root = get_full_data_path ("hf_models" )
911923 name_dir = make_safe_directory_name (repo_id )
912- root_project = os . path . join (hf_root , name_dir )
924+ root_project = safe_path_join (hf_root , name_dir )
913925 if filename :
914926 output_path = hf_hub_download (
915927 repo_id = repo_id , filename = filename , local_dir = root_project
0 commit comments