@@ -121,15 +121,20 @@ and send_dir ~src_dir ~dst ~to_untar ~user items =
121121 copy_dir ~src_dir ~src ~dst ~items ~to_untar ~user
122122 )
123123
124- let remove_leading_slashes s =
124+ let normalize_path s =
125125 (* Strip Windows drive letter prefix (e.g. "C:/") *)
126126 let s =
127127 if String. length s > = 2 && Char. uppercase_ascii s.[0 ] > = 'A' &&
128128 Char. uppercase_ascii s.[0 ] < = 'Z' && s.[1 ] = ':' then
129129 String. sub s 2 (String. length s - 2 )
130130 else s
131131 in
132- Astring.String. drop ~sat: ((= ) '/' ) s
132+ (* Drop leading slashes and any "." or empty path components. openSUSE's
133+ backport of CVE-2025-45582 to tar 1.34 walks paths with openat() and
134+ fails on "./" segments in the header path. *)
135+ String. split_on_char '/' s
136+ |> List. filter (fun p -> p <> " " && p <> " ." )
137+ |> String. concat " /"
133138
134139let ensure_dir_entries ~to_untar ~user path =
135140 (* Emit tar directory entries for each component of path so that
@@ -150,13 +155,13 @@ let ensure_dir_entries ~to_untar ~user path =
150155 loop " " parts
151156
152157let send_files ~src_dir ~src_manifest ~dst_dir ~user ~to_untar =
153- let dst = remove_leading_slashes dst_dir in
158+ let dst = normalize_path dst_dir in
154159 ensure_dir_entries ~to_untar ~user dst >> = fun () ->
155160 send_dir ~src_dir ~dst ~to_untar ~user src_manifest >> = fun () ->
156161 Tar_lwt_unix. write_end to_untar
157162
158163let send_file ~src_dir ~src_manifest ~dst ~user ~to_untar =
159- let dst = remove_leading_slashes dst in
164+ let dst = normalize_path dst in
160165 begin
161166 match src_manifest with
162167 | `File (path , _ ) ->
@@ -214,7 +219,7 @@ let rec map_transform ~dst transformations = function
214219 List. iter (map_transform ~dst transformations) items
215220
216221and transform_files ~from_tar ~src_manifest ~dst_dir ~user ~to_untar =
217- let dst = remove_leading_slashes dst_dir in
222+ let dst = normalize_path dst_dir in
218223 let transformations = Hashtbl. create ~random: true 64 in
219224 List. iter (map_transform ~dst transformations) src_manifest;
220225 let fname file_name =
@@ -225,7 +230,7 @@ and transform_files ~from_tar ~src_manifest ~dst_dir ~user ~to_untar =
225230 Tar_lwt_unix.Archive. transform ~level (transform ~user fname) from_tar to_untar
226231
227232let transform_file ~from_tar ~src_manifest ~dst ~user ~to_untar =
228- let dst = remove_leading_slashes dst in
233+ let dst = normalize_path dst in
229234 let transformations = Hashtbl. create ~random: true 1 in
230235 let map_transform = function
231236 | `File (src , _ ) -> Hashtbl. add transformations src dst
0 commit comments