@@ -226,6 +226,44 @@ def mock_download_and_unpack_zip_impl(url, download_artifact_temp_dir,
226226 os .path .join (artifact_download_dst_dir ,
227227 os .path .basename (self .testcase ))))
228228
229+ @mock .patch ('filestore.github_actions.GithubActionsFilestore._find_artifact' )
230+ @mock .patch ('http_utils.download_and_unpack_zip' )
231+ def test_download_build_rejects_traversal_tar_member (
232+ self , mock_download_and_unpack_zip , mock_find_artifact ):
233+ """Tests that traversal tar entries are rejected."""
234+ artifact_name = 'cifuzz-build-address-commit'
235+
236+ def fake_download_and_unpack_zip (download_url , dst_directory , headers = None ):
237+ del download_url , headers
238+ tar_path = os .path .join (dst_directory , artifact_name + '.tar' )
239+ safe_file = os .path .join (dst_directory , 'demo_fuzzer' )
240+ traversal_file = os .path .join (dst_directory , 'escape.txt' )
241+
242+ with open (safe_file , 'w' , encoding = 'utf-8' ) as file_handle :
243+ file_handle .write ('demo' )
244+
245+ with open (traversal_file , 'w' , encoding = 'utf-8' ) as file_handle :
246+ file_handle .write ('escape' )
247+
248+ with tarfile .open (tar_path , 'w' ) as tar_handle :
249+ tar_handle .add (safe_file , arcname = 'demo_fuzzer' )
250+ tar_handle .add (traversal_file , arcname = '../escape.txt' )
251+ return True
252+
253+ mock_download_and_unpack_zip .side_effect = fake_download_and_unpack_zip
254+ mock_find_artifact .return_value = {
255+ 'expired' : False ,
256+ 'name' : artifact_name ,
257+ 'archive_download_url' : 'http://example.com/download'
258+ }
259+
260+ filestore = github_actions .GithubActionsFilestore (self .config )
261+ result = filestore .download_build ('address-commit' , self .local_dir )
262+
263+ self .assertFalse (result )
264+ self .assertFalse (
265+ os .path .exists (os .path .join (self .local_dir , 'demo_fuzzer' )))
266+
229267 @mock .patch ('filestore.github_actions.github_api.list_artifacts' )
230268 def test_find_artifact (self , mock_list_artifacts ):
231269 """Tests that _find_artifact works as intended."""
0 commit comments