@@ -149,6 +149,31 @@ def test_extract_image_source_info_errors(self, test_files_path):
149149 with pytest .raises (ValueError , match = "missing the 'page_number' key" ):
150150 _extract_image_sources_info (documents = [document ], file_path_meta_field = "file_path" , root_path = "" )
151151
152+ def test_extract_image_source_info_rejects_path_traversal (self , test_files_path ):
153+ # Attacker-controlled document metadata attempts to escape the configured root.
154+ document = Document (content = "test" , meta = {"file_path" : "../../../../../../etc/passwd" })
155+ with pytest .raises (ValueError , match = "escapes the configured root" ):
156+ _extract_image_sources_info (
157+ documents = [document ], file_path_meta_field = "file_path" , root_path = str (test_files_path / "images" )
158+ )
159+
160+ def test_extract_image_source_info_rejects_absolute_outside_root (self , test_files_path ):
161+ # Absolute path that lies outside the configured root must be rejected before any IO.
162+ document = Document (content = "test" , meta = {"file_path" : "/etc/passwd" })
163+ with pytest .raises (ValueError , match = "escapes the configured root" ):
164+ _extract_image_sources_info (
165+ documents = [document ], file_path_meta_field = "file_path" , root_path = str (test_files_path / "images" )
166+ )
167+
168+ def test_extract_image_source_info_accepts_path_inside_root (self , test_files_path ):
169+ # When the resolved path is inside the configured root, processing must succeed.
170+ document = Document (content = "test" , meta = {"file_path" : "haystack-logo.png" })
171+ images_source_info = _extract_image_sources_info (
172+ documents = [document ], file_path_meta_field = "file_path" , root_path = str (test_files_path / "images" )
173+ )
174+ assert len (images_source_info ) == 1
175+ assert images_source_info [0 ]["mime_type" ] == "image/png"
176+
152177
153178class TestBatchConvertPdfPagesToImages :
154179 @patch ("haystack.components.converters.image.image_utils._convert_pdf_to_images" )
0 commit comments