prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [BUG] Security Vulnerability
  Please check it here https://huntr.com/bounties/e3d7a994-bfd6-4772-ac9b-9aee1aa16a5f/
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `mlflow/store/artifact/local_artifact_repo.py`
  Content:
  ```
  1 import os
  2 import shutil
  3 
  4 from mlflow.store.artifact.artifact_repo import ArtifactRepository, verify_artifact_path
  5 from mlflow.utils.file_utils import (
  6     get_file_info,
  7     list_all,
  8     local_file_uri_to_path,
  9     mkdir,
  10     relative_path_to_artifact_path,
  11 )
  12 
  13 
  14 class LocalArtifactRepository(ArtifactRepository):
  15     """Stores artifacts as files in a local directory."""
  16 
  17     def __init__(self, *args, **kwargs):
  18         super().__init__(*args, **kwargs)
  19         self._artifact_dir = local_file_uri_to_path(self.artifact_uri)
  20 
  21     @property
  22     def artifact_dir(self):
  23         return self._artifact_dir
  24 
  25     def log_artifact(self, local_file, artifact_path=None):
  26         verify_artifact_path(artifact_path)
  27         # NOTE: The artifact_path is expected to be in posix format.
  28         # Posix paths work fine on windows but just in case we normalize it here.
  29         if artifact_path:
  30             artifact_path = os.path.normpath(artifact_path)
  31 
  32         artifact_dir = (
  33             os.path.join(self.artifact_dir, artifact_path) if artifact_path else self.artifact_dir
  34         )
  35         if not os.path.exists(artifact_dir):
  36             mkdir(artifact_dir)
  37         try:
  38             shutil.copy2(local_file, os.path.join(artifact_dir, os.path.basename(local_file)))
  39         except shutil.SameFileError:
  40             pass
  41 
  42     def _is_directory(self, artifact_path):
  43         # NOTE: The path is expected to be in posix format.
  44         # Posix paths work fine on windows but just in case we normalize it here.
  45         path = os.path.normpath(artifact_path) if artifact_path else ""
  46         list_dir = os.path.join(self.artifact_dir, path) if path else self.artifact_dir
  47         return os.path.isdir(list_dir)
  48 
  49     def log_artifacts(self, local_dir, artifact_path=None):
  50         verify_artifact_path(artifact_path)
  51         # NOTE: The artifact_path is expected to be in posix format.
  52         # Posix paths work fine on windows but just in case we normalize it here.
  53         if artifact_path:
  54             artifact_path = os.path.normpath(artifact_path)
  55         artifact_dir = (
  56             os.path.join(self.artifact_dir, artifact_path) if artifact_path else self.artifact_dir
  57         )
  58         if not os.path.exists(artifact_dir):
  59             mkdir(artifact_dir)
  60         shutil.copytree(src=local_dir, dst=artifact_dir, dirs_exist_ok=True)
  61 
  62     def download_artifacts(self, artifact_path, dst_path=None):
  63         """
  64         Artifacts tracked by ``LocalArtifactRepository`` already exist on the local filesystem.
  65         If ``dst_path`` is ``None``, the absolute filesystem path of the specified artifact is
  66         returned. If ``dst_path`` is not ``None``, the local artifact is copied to ``dst_path``.
  67 
  68         :param artifact_path: Relative source path to the desired artifacts.
  69         :param dst_path: Absolute path of the local filesystem destination directory to which to
  70                          download the specified artifacts. This directory must already exist. If
  71                          unspecified, the absolute path of the local artifact will be returned.
  72 
  73         :return: Absolute path of the local filesystem location containing the desired artifacts.
  74         """
  75         if dst_path:
  76             return super().download_artifacts(artifact_path, dst_path)
  77         # NOTE: The artifact_path is expected to be in posix format.
  78         # Posix paths work fine on windows but just in case we normalize it here.
  79         local_artifact_path = os.path.join(self.artifact_dir, os.path.normpath(artifact_path))
  80         if not os.path.exists(local_artifact_path):
  81             raise OSError(f"No such file or directory: '{local_artifact_path}'")
  82         return os.path.abspath(local_artifact_path)
  83 
  84     def list_artifacts(self, path=None):
  85         # NOTE: The path is expected to be in posix format.
  86         # Posix paths work fine on windows but just in case we normalize it here.
  87         if path:
  88             path = os.path.normpath(path)
  89         list_dir = os.path.join(self.artifact_dir, path) if path else self.artifact_dir
  90         if os.path.isdir(list_dir):
  91             artifact_files = list_all(list_dir, full_path=True)
  92             infos = [
  93                 get_file_info(
  94                     f, relative_path_to_artifact_path(os.path.relpath(f, self.artifact_dir))
  95                 )
  96                 for f in artifact_files
  97             ]
  98             return sorted(infos, key=lambda f: f.path)
  99         else:
  100             return []
  101 
  102     def _download_file(self, remote_file_path, local_path):
  103         # NOTE: The remote_file_path is expected to be in posix format.
  104         # Posix paths work fine on windows but just in case we normalize it here.
  105         remote_file_path = os.path.join(self.artifact_dir, os.path.normpath(remote_file_path))
  106         shutil.copy2(remote_file_path, local_path)
  107 
  108     def delete_artifacts(self, artifact_path=None):
  109         artifact_path = local_file_uri_to_path(
  110             os.path.join(self._artifact_dir, artifact_path) if artifact_path else self._artifact_dir
  111         )
  112 
  113         if os.path.exists(artifact_path):
  114             shutil.rmtree(artifact_path)
  115
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/mlflow/store/artifact/local_artifact_repo.py b/mlflow/store/artifact/local_artifact_repo.py
  --- a/mlflow/store/artifact/local_artifact_repo.py
  +++ b/mlflow/store/artifact/local_artifact_repo.py
  @@ -9,6 +9,7 @@
       mkdir,
       relative_path_to_artifact_path,
   )
  +from mlflow.utils.uri import validate_path_is_safe
   
   
   class LocalArtifactRepository(ArtifactRepository):
  @@ -74,8 +75,9 @@
           """
           if dst_path:
               return super().download_artifacts(artifact_path, dst_path)
  -        # NOTE: The artifact_path is expected to be in posix format.
  +        # NOTE: The artifact_path is expected to be a relative path in posix format.
           # Posix paths work fine on windows but just in case we normalize it here.
  +        artifact_path = validate_path_is_safe(artifact_path)
           local_artifact_path = os.path.join(self.artifact_dir, os.path.normpath(artifact_path))
           if not os.path.exists(local_artifact_path):
               raise OSError(f"No such file or directory: '{local_artifact_path}'")
  @@ -100,8 +102,9 @@
               return []
   
       def _download_file(self, remote_file_path, local_path):
  -        # NOTE: The remote_file_path is expected to be in posix format.
  +        # NOTE: The remote_file_path is expected to be a relative path in posix format.
           # Posix paths work fine on windows but just in case we normalize it here.
  +        remote_file_path = validate_path_is_safe(remote_file_path)
           remote_file_path = os.path.join(self.artifact_dir, os.path.normpath(remote_file_path))
           shutil.copy2(remote_file_path, local_path)
  
verification_info: {"golden_diff": "diff --git a/mlflow/store/artifact/local_artifact_repo.py b/mlflow/store/artifact/local_artifact_repo.py\n--- a/mlflow/store/artifact/local_artifact_repo.py\n+++ b/mlflow/store/artifact/local_artifact_repo.py\n@@ -9,6 +9,7 @@\n     mkdir,\n     relative_path_to_artifact_path,\n )\n+from mlflow.utils.uri import validate_path_is_safe\n \n \n class LocalArtifactRepository(ArtifactRepository):\n@@ -74,8 +75,9 @@\n         \"\"\"\n         if dst_path:\n             return super().download_artifacts(artifact_path, dst_path)\n-        # NOTE: The artifact_path is expected to be in posix format.\n+        # NOTE: The artifact_path is expected to be a relative path in posix format.\n         # Posix paths work fine on windows but just in case we normalize it here.\n+        artifact_path = validate_path_is_safe(artifact_path)\n         local_artifact_path = os.path.join(self.artifact_dir, os.path.normpath(artifact_path))\n         if not os.path.exists(local_artifact_path):\n             raise OSError(f\"No such file or directory: '{local_artifact_path}'\")\n@@ -100,8 +102,9 @@\n             return []\n \n     def _download_file(self, remote_file_path, local_path):\n-        # NOTE: The remote_file_path is expected to be in posix format.\n+        # NOTE: The remote_file_path is expected to be a relative path in posix format.\n         # Posix paths work fine on windows but just in case we normalize it here.\n+        remote_file_path = validate_path_is_safe(remote_file_path)\n         remote_file_path = os.path.join(self.artifact_dir, os.path.normpath(remote_file_path))\n         shutil.copy2(remote_file_path, local_path)\n", "issue": "[BUG] Security Vulnerability\nPlease check it here https://huntr.com/bounties/e3d7a994-bfd6-4772-ac9b-9aee1aa16a5f/\n", "before_files": [{"content": "import os\nimport shutil\n\nfrom mlflow.store.artifact.artifact_repo import ArtifactRepository, verify_artifact_path\nfrom mlflow.utils.file_utils import (\n    get_file_info,\n    list_all,\n    local_file_uri_to_path,\n    mkdir,\n    relative_path_to_artifact_path,\n)\n\n\nclass LocalArtifactRepository(ArtifactRepository):\n    \"\"\"Stores artifacts as files in a local directory.\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self._artifact_dir = local_file_uri_to_path(self.artifact_uri)\n\n    @property\n    def artifact_dir(self):\n        return self._artifact_dir\n\n    def log_artifact(self, local_file, artifact_path=None):\n        verify_artifact_path(artifact_path)\n        # NOTE: The artifact_path is expected to be in posix format.\n        # Posix paths work fine on windows but just in case we normalize it here.\n        if artifact_path:\n            artifact_path = os.path.normpath(artifact_path)\n\n        artifact_dir = (\n            os.path.join(self.artifact_dir, artifact_path) if artifact_path else self.artifact_dir\n        )\n        if not os.path.exists(artifact_dir):\n            mkdir(artifact_dir)\n        try:\n            shutil.copy2(local_file, os.path.join(artifact_dir, os.path.basename(local_file)))\n        except shutil.SameFileError:\n            pass\n\n    def _is_directory(self, artifact_path):\n        # NOTE: The path is expected to be in posix format.\n        # Posix paths work fine on windows but just in case we normalize it here.\n        path = os.path.normpath(artifact_path) if artifact_path else \"\"\n        list_dir = os.path.join(self.artifact_dir, path) if path else self.artifact_dir\n        return os.path.isdir(list_dir)\n\n    def log_artifacts(self, local_dir, artifact_path=None):\n        verify_artifact_path(artifact_path)\n        # NOTE: The artifact_path is expected to be in posix format.\n        # Posix paths work fine on windows but just in case we normalize it here.\n        if artifact_path:\n            artifact_path = os.path.normpath(artifact_path)\n        artifact_dir = (\n            os.path.join(self.artifact_dir, artifact_path) if artifact_path else self.artifact_dir\n        )\n        if not os.path.exists(artifact_dir):\n            mkdir(artifact_dir)\n        shutil.copytree(src=local_dir, dst=artifact_dir, dirs_exist_ok=True)\n\n    def download_artifacts(self, artifact_path, dst_path=None):\n        \"\"\"\n        Artifacts tracked by ``LocalArtifactRepository`` already exist on the local filesystem.\n        If ``dst_path`` is ``None``, the absolute filesystem path of the specified artifact is\n        returned. If ``dst_path`` is not ``None``, the local artifact is copied to ``dst_path``.\n\n        :param artifact_path: Relative source path to the desired artifacts.\n        :param dst_path: Absolute path of the local filesystem destination directory to which to\n                         download the specified artifacts. This directory must already exist. If\n                         unspecified, the absolute path of the local artifact will be returned.\n\n        :return: Absolute path of the local filesystem location containing the desired artifacts.\n        \"\"\"\n        if dst_path:\n            return super().download_artifacts(artifact_path, dst_path)\n        # NOTE: The artifact_path is expected to be in posix format.\n        # Posix paths work fine on windows but just in case we normalize it here.\n        local_artifact_path = os.path.join(self.artifact_dir, os.path.normpath(artifact_path))\n        if not os.path.exists(local_artifact_path):\n            raise OSError(f\"No such file or directory: '{local_artifact_path}'\")\n        return os.path.abspath(local_artifact_path)\n\n    def list_artifacts(self, path=None):\n        # NOTE: The path is expected to be in posix format.\n        # Posix paths work fine on windows but just in case we normalize it here.\n        if path:\n            path = os.path.normpath(path)\n        list_dir = os.path.join(self.artifact_dir, path) if path else self.artifact_dir\n        if os.path.isdir(list_dir):\n            artifact_files = list_all(list_dir, full_path=True)\n            infos = [\n                get_file_info(\n                    f, relative_path_to_artifact_path(os.path.relpath(f, self.artifact_dir))\n                )\n                for f in artifact_files\n            ]\n            return sorted(infos, key=lambda f: f.path)\n        else:\n            return []\n\n    def _download_file(self, remote_file_path, local_path):\n        # NOTE: The remote_file_path is expected to be in posix format.\n        # Posix paths work fine on windows but just in case we normalize it here.\n        remote_file_path = os.path.join(self.artifact_dir, os.path.normpath(remote_file_path))\n        shutil.copy2(remote_file_path, local_path)\n\n    def delete_artifacts(self, artifact_path=None):\n        artifact_path = local_file_uri_to_path(\n            os.path.join(self._artifact_dir, artifact_path) if artifact_path else self._artifact_dir\n        )\n\n        if os.path.exists(artifact_path):\n            shutil.rmtree(artifact_path)\n", "path": "mlflow/store/artifact/local_artifact_repo.py"}], "after_files": [{"content": "import os\nimport shutil\n\nfrom mlflow.store.artifact.artifact_repo import ArtifactRepository, verify_artifact_path\nfrom mlflow.utils.file_utils import (\n    get_file_info,\n    list_all,\n    local_file_uri_to_path,\n    mkdir,\n    relative_path_to_artifact_path,\n)\nfrom mlflow.utils.uri import validate_path_is_safe\n\n\nclass LocalArtifactRepository(ArtifactRepository):\n    \"\"\"Stores artifacts as files in a local directory.\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self._artifact_dir = local_file_uri_to_path(self.artifact_uri)\n\n    @property\n    def artifact_dir(self):\n        return self._artifact_dir\n\n    def log_artifact(self, local_file, artifact_path=None):\n        verify_artifact_path(artifact_path)\n        # NOTE: The artifact_path is expected to be in posix format.\n        # Posix paths work fine on windows but just in case we normalize it here.\n        if artifact_path:\n            artifact_path = os.path.normpath(artifact_path)\n\n        artifact_dir = (\n            os.path.join(self.artifact_dir, artifact_path) if artifact_path else self.artifact_dir\n        )\n        if not os.path.exists(artifact_dir):\n            mkdir(artifact_dir)\n        try:\n            shutil.copy2(local_file, os.path.join(artifact_dir, os.path.basename(local_file)))\n        except shutil.SameFileError:\n            pass\n\n    def _is_directory(self, artifact_path):\n        # NOTE: The path is expected to be in posix format.\n        # Posix paths work fine on windows but just in case we normalize it here.\n        path = os.path.normpath(artifact_path) if artifact_path else \"\"\n        list_dir = os.path.join(self.artifact_dir, path) if path else self.artifact_dir\n        return os.path.isdir(list_dir)\n\n    def log_artifacts(self, local_dir, artifact_path=None):\n        verify_artifact_path(artifact_path)\n        # NOTE: The artifact_path is expected to be in posix format.\n        # Posix paths work fine on windows but just in case we normalize it here.\n        if artifact_path:\n            artifact_path = os.path.normpath(artifact_path)\n        artifact_dir = (\n            os.path.join(self.artifact_dir, artifact_path) if artifact_path else self.artifact_dir\n        )\n        if not os.path.exists(artifact_dir):\n            mkdir(artifact_dir)\n        shutil.copytree(src=local_dir, dst=artifact_dir, dirs_exist_ok=True)\n\n    def download_artifacts(self, artifact_path, dst_path=None):\n        \"\"\"\n        Artifacts tracked by ``LocalArtifactRepository`` already exist on the local filesystem.\n        If ``dst_path`` is ``None``, the absolute filesystem path of the specified artifact is\n        returned. If ``dst_path`` is not ``None``, the local artifact is copied to ``dst_path``.\n\n        :param artifact_path: Relative source path to the desired artifacts.\n        :param dst_path: Absolute path of the local filesystem destination directory to which to\n                         download the specified artifacts. This directory must already exist. If\n                         unspecified, the absolute path of the local artifact will be returned.\n\n        :return: Absolute path of the local filesystem location containing the desired artifacts.\n        \"\"\"\n        if dst_path:\n            return super().download_artifacts(artifact_path, dst_path)\n        # NOTE: The artifact_path is expected to be a relative path in posix format.\n        # Posix paths work fine on windows but just in case we normalize it here.\n        artifact_path = validate_path_is_safe(artifact_path)\n        local_artifact_path = os.path.join(self.artifact_dir, os.path.normpath(artifact_path))\n        if not os.path.exists(local_artifact_path):\n            raise OSError(f\"No such file or directory: '{local_artifact_path}'\")\n        return os.path.abspath(local_artifact_path)\n\n    def list_artifacts(self, path=None):\n        # NOTE: The path is expected to be in posix format.\n        # Posix paths work fine on windows but just in case we normalize it here.\n        if path:\n            path = os.path.normpath(path)\n        list_dir = os.path.join(self.artifact_dir, path) if path else self.artifact_dir\n        if os.path.isdir(list_dir):\n            artifact_files = list_all(list_dir, full_path=True)\n            infos = [\n                get_file_info(\n                    f, relative_path_to_artifact_path(os.path.relpath(f, self.artifact_dir))\n                )\n                for f in artifact_files\n            ]\n            return sorted(infos, key=lambda f: f.path)\n        else:\n            return []\n\n    def _download_file(self, remote_file_path, local_path):\n        # NOTE: The remote_file_path is expected to be a relative path in posix format.\n        # Posix paths work fine on windows but just in case we normalize it here.\n        remote_file_path = validate_path_is_safe(remote_file_path)\n        remote_file_path = os.path.join(self.artifact_dir, os.path.normpath(remote_file_path))\n        shutil.copy2(remote_file_path, local_path)\n\n    def delete_artifacts(self, artifact_path=None):\n        artifact_path = local_file_uri_to_path(\n            os.path.join(self._artifact_dir, artifact_path) if artifact_path else self._artifact_dir\n        )\n\n        if os.path.exists(artifact_path):\n            shutil.rmtree(artifact_path)\n", "path": "mlflow/store/artifact/local_artifact_repo.py"}]}