@@ -952,36 +952,34 @@ def test_zip_files(self) -> None:
952952
953953 def test_get_download_url_and_local_filename_with_valid_config (self ) -> None :
954954 """Test get_download_url_and_local_filename with valid configuration."""
955- lfs = LocalFilesystem (
956- "vehicle_dir" , "vehicle_type" , None , allow_editing_template_files = False , save_component_to_system_templates = False
957- )
958-
959- # Set up configuration steps with download file section
960- lfs . configuration_steps = {
961- "test_file.param " : {
962- "download_file" : { "source_url" : "https://example.com/file.bin" , "dest_local" : "local_file.bin" }
955+ with tempfile . TemporaryDirectory () as tmp_dir :
956+ lfs = LocalFilesystem (
957+ tmp_dir , "vehicle_type" , None , allow_editing_template_files = False , save_component_to_system_templates = False
958+ )
959+ lfs . configuration_steps = {
960+ "test_file.param" : {
961+ "download_file " : {"source_url" : "https://example.com/file.bin" , "dest_local" : "local_file.bin" }
962+ }
963963 }
964- }
965964
966- with patch ("os.path.join" , return_value = "vehicle_dir/local_file.bin" ):
967965 url , local_path = lfs .get_download_url_and_local_filename ("test_file.param" )
968966 assert url == "https://example.com/file.bin"
969- assert local_path == "vehicle_dir/ local_file.bin"
967+ assert local_path == os_path . realpath ( os_path . join ( tmp_dir , " local_file.bin"))
970968
971969 def test_get_upload_local_and_remote_filenames_with_valid_config (self ) -> None :
972970 """Test get_upload_local_and_remote_filenames with valid configuration."""
973- lfs = LocalFilesystem (
974- "vehicle_dir" , "vehicle_type" , None , allow_editing_template_files = False , save_component_to_system_templates = False
975- )
976-
977- # Set up configuration steps with upload file section
978- lfs .configuration_steps = {
979- "test_file.param" : {"upload_file" : {"source_local" : "local_file.bin" , "dest_on_fc" : "/fs/microsd/APM/file.bin" }}
980- }
971+ with tempfile .TemporaryDirectory () as tmp_dir :
972+ lfs = LocalFilesystem (
973+ tmp_dir , "vehicle_type" , None , allow_editing_template_files = False , save_component_to_system_templates = False
974+ )
975+ lfs .configuration_steps = {
976+ "test_file.param" : {
977+ "upload_file" : {"source_local" : "local_file.bin" , "dest_on_fc" : "/fs/microsd/APM/file.bin" }
978+ }
979+ }
981980
982- with patch ("os.path.join" , return_value = "vehicle_dir/local_file.bin" ):
983981 local_path , remote_path = lfs .get_upload_local_and_remote_filenames ("test_file.param" )
984- assert local_path == "vehicle_dir/ local_file.bin"
982+ assert local_path == os_path . realpath ( os_path . join ( tmp_dir , " local_file.bin"))
985983 assert remote_path == "/fs/microsd/APM/file.bin"
986984
987985
@@ -1061,6 +1059,49 @@ def test_download_rejects_absolute_path(self, tmp_path) -> None:
10611059 with pytest .raises (ValueError , match = "Path escapes vehicle directory" ):
10621060 lfs .get_download_url_and_local_filename ("test.param" )
10631061
1062+ def test_download_rejects_dest_local_resolving_to_base_dir (self , tmp_path ) -> None :
1063+ """
1064+ dest_local='.' resolves to vehicle_dir itself and is rejected.
1065+
1066+ GIVEN: A configuration step with dest_local='.' (resolves to base directory)
1067+ WHEN: get_download_url_and_local_filename is called
1068+ THEN: A ValueError is raised because a directory path is not a valid file target
1069+ """
1070+ lfs = LocalFilesystem (
1071+ str (tmp_path ), "vehicle_type" , None , allow_editing_template_files = False , save_component_to_system_templates = False
1072+ )
1073+ lfs .configuration_steps = {
1074+ "test.param" : {"download_file" : {"source_url" : "https://example.com/payload" , "dest_local" : "." }}
1075+ }
1076+
1077+ with pytest .raises (ValueError , match = "Path escapes vehicle directory" ):
1078+ lfs .get_download_url_and_local_filename ("test.param" )
1079+
1080+ def test_download_rejects_symlink_escape (self , tmp_path ) -> None :
1081+ """
1082+ Symlink pointing outside vehicle_dir is blocked.
1083+
1084+ GIVEN: A symlink inside vehicle_dir that points to an external directory
1085+ WHEN: dest_local references a file through the symlink
1086+ THEN: A ValueError is raised because the resolved path escapes vehicle_dir
1087+ """
1088+ # Create a symlink inside tmp_path pointing to /tmp
1089+ symlink_path = tmp_path / "escape_link"
1090+ try :
1091+ symlink_path .symlink_to ("/tmp" )
1092+ except OSError :
1093+ pytest .skip ("Cannot create symlinks in this environment" )
1094+
1095+ lfs = LocalFilesystem (
1096+ str (tmp_path ), "vehicle_type" , None , allow_editing_template_files = False , save_component_to_system_templates = False
1097+ )
1098+ lfs .configuration_steps = {
1099+ "test.param" : {"download_file" : {"source_url" : "https://example.com/payload" , "dest_local" : "escape_link/evil" }}
1100+ }
1101+
1102+ with pytest .raises (ValueError , match = "Path escapes vehicle directory" ):
1103+ lfs .get_download_url_and_local_filename ("test.param" )
1104+
10641105
10651106class TestTransformParamDict :
10661107 """Unit tests for LocalFilesystem._transform_param_dict (pure in-memory, no filesystem)."""
0 commit comments