prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Yaml loader should be replaced by safe_loader or other more secure loader
  To load yaml files from unknown source, we should avoid using yaml's loader.  A better way is to use either safe_loader or other mechanism.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `nvflare/lighter/provision.py`
  Content:
  ```
  1 # Copyright (c) 2021-2022, NVIDIA CORPORATION.  All rights reserved.
  2 #
  3 # Licensed under the Apache License, Version 2.0 (the "License");
  4 # you may not use this file except in compliance with the License.
  5 # You may obtain a copy of the License at
  6 #
  7 #     http://www.apache.org/licenses/LICENSE-2.0
  8 #
  9 # Unless required by applicable law or agreed to in writing, software
  10 # distributed under the License is distributed on an "AS IS" BASIS,
  11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 # See the License for the specific language governing permissions and
  13 # limitations under the License.
  14 
  15 from __future__ import absolute_import
  16 
  17 import argparse
  18 import os
  19 import pathlib
  20 import shutil
  21 import sys
  22 import webbrowser
  23 
  24 import yaml
  25 
  26 from nvflare.fuel.utils.class_utils import instantiate_class
  27 from nvflare.lighter.spec import Participant, Project, Provisioner
  28 
  29 
  30 def main():
  31     parser = argparse.ArgumentParser()
  32     parser.add_argument("-p", "--project_file", type=str, default="project.yml", help="file to describe FL project")
  33     parser.add_argument("-w", "--workspace", type=str, default="workspace", help="directory used by provision")
  34     parser.add_argument("-c", "--custom_folder", type=str, default=".", help="additional folder to load python codes")
  35     parser.add_argument(
  36         "-u",
  37         "--ui_tool",
  38         action="store_true",
  39         help="Run provisioning UI tool to generate project.yml file",
  40     )
  41 
  42     args = parser.parse_args()
  43 
  44     file_path = pathlib.Path(__file__).parent.absolute()
  45     current_path = os.getcwd()
  46     custom_folder_path = os.path.join(current_path, args.custom_folder)
  47     sys.path.append(custom_folder_path)
  48     print("Path list (sys.path) for python codes loading: {}".format(sys.path))
  49 
  50     # main project file
  51     project_file = args.project_file
  52     current_project_yml = os.path.join(current_path, "project.yml")
  53     if len(sys.argv) == 1 and not os.path.exists(current_project_yml):
  54         answer = input(
  55             f"No project.yml found in current folder.  Is it OK to generate one at {current_project_yml} for you? (y/N) "
  56         )
  57         if answer.strip().upper() == "Y":
  58             shutil.copyfile(os.path.join(file_path, "project.yml"), current_project_yml)
  59             print(f"{current_project_yml} was created.  Please edit it to fit your FL configuration.")
  60         exit(0)
  61 
  62     if args.ui_tool:
  63         ui_helper_path = os.path.join(file_path, "provision_helper.html")
  64         ui_helper_url = f"file://{ui_helper_path}"
  65         webbrowser.open_new_tab(ui_helper_url)
  66         print(
  67             "\n******\n"
  68             "Now launching provisioning UI tool.\n"
  69             "After generating project.yml in the browser and saving it to your local folder,\n"
  70             "please re-run provision with -p option, pointing to the generated project.yml, to generate all packages.\n******\n"
  71         )
  72         exit(0)
  73 
  74     workspace = args.workspace
  75     workspace_full_path = os.path.join(current_path, workspace)
  76 
  77     project_full_path = os.path.join(current_path, project_file)
  78     print(f"Project yaml file: {project_full_path}.")
  79 
  80     project_dict = yaml.load(open(project_full_path, "r"), Loader=yaml.Loader)
  81     api_version = project_dict.get("api_version")
  82     if api_version not in [3]:
  83         raise ValueError(f"API version expected 3 but found {api_version}")
  84 
  85     project_name = project_dict.get("name")
  86     project_description = project_dict.get("description", "")
  87     participants = list()
  88     for p in project_dict.get("participants"):
  89         participants.append(Participant(**p))
  90     project = Project(name=project_name, description=project_description, participants=participants)
  91 
  92     builders = list()
  93     for b in project_dict.get("builders"):
  94         path = b.get("path")
  95         args = b.get("args")
  96         builders.append(instantiate_class(path, args))
  97 
  98     provisioner = Provisioner(workspace_full_path, builders)
  99 
  100     provisioner.provision(project)
  101 
  102 
  103 if __name__ == "__main__":
  104     main()
  105
  ```
  
  Path: `nvflare/lighter/utils.py`
  Content:
  ```
  1 # Copyright (c) 2021-2022, NVIDIA CORPORATION.  All rights reserved.
  2 #
  3 # Licensed under the Apache License, Version 2.0 (the "License");
  4 # you may not use this file except in compliance with the License.
  5 # You may obtain a copy of the License at
  6 #
  7 #     http://www.apache.org/licenses/LICENSE-2.0
  8 #
  9 # Unless required by applicable law or agreed to in writing, software
  10 # distributed under the License is distributed on an "AS IS" BASIS,
  11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 # See the License for the specific language governing permissions and
  13 # limitations under the License.
  14 
  15 import os
  16 import random
  17 from base64 import b64encode
  18 
  19 import yaml
  20 from cryptography.hazmat.primitives import hashes
  21 from cryptography.hazmat.primitives.asymmetric import padding
  22 
  23 
  24 def generate_password():
  25     s = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  26     passlen = 16
  27     p = "".join(random.sample(s, passlen))
  28     return p
  29 
  30 
  31 def sign_all(content_folder, signing_pri_key):
  32     signatures = dict()
  33     for f in os.listdir(content_folder):
  34         path = os.path.join(content_folder, f)
  35         if os.path.isfile(path):
  36             signature = signing_pri_key.sign(
  37                 data=open(path, "rb").read(),
  38                 padding=padding.PSS(
  39                     mgf=padding.MGF1(hashes.SHA256()),
  40                     salt_length=padding.PSS.MAX_LENGTH,
  41                 ),
  42                 algorithm=hashes.SHA256(),
  43             )
  44             signatures[f] = b64encode(signature).decode("utf-8")
  45     return signatures
  46 
  47 
  48 def load_yaml(file_name):
  49     return yaml.load(open(file_name, "r"), Loader=yaml.Loader)
  50 
  51 
  52 def sh_replace(src, mapping_dict):
  53     result = src
  54     for k, v in mapping_dict.items():
  55         result = result.replace("{~~" + k + "~~}", str(v))
  56     return result
  57
  ```
  --- 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/nvflare/lighter/provision.py b/nvflare/lighter/provision.py
  --- a/nvflare/lighter/provision.py
  +++ b/nvflare/lighter/provision.py
  @@ -21,10 +21,9 @@
   import sys
   import webbrowser
   
  -import yaml
  -
   from nvflare.fuel.utils.class_utils import instantiate_class
   from nvflare.lighter.spec import Participant, Project, Provisioner
  +from nvflare.lighter.utils import load_yaml
   
   
   def main():
  @@ -77,7 +76,7 @@
       project_full_path = os.path.join(current_path, project_file)
       print(f"Project yaml file: {project_full_path}.")
   
  -    project_dict = yaml.load(open(project_full_path, "r"), Loader=yaml.Loader)
  +    project_dict = load_yaml(project_full_path)
       api_version = project_dict.get("api_version")
       if api_version not in [3]:
           raise ValueError(f"API version expected 3 but found {api_version}")
  diff --git a/nvflare/lighter/utils.py b/nvflare/lighter/utils.py
  --- a/nvflare/lighter/utils.py
  +++ b/nvflare/lighter/utils.py
  @@ -46,7 +46,7 @@
   
   
   def load_yaml(file_name):
  -    return yaml.load(open(file_name, "r"), Loader=yaml.Loader)
  +    return yaml.safe_load(open(file_name, "r"))
   
   
   def sh_replace(src, mapping_dict):
  
verification_info: {"golden_diff": "diff --git a/nvflare/lighter/provision.py b/nvflare/lighter/provision.py\n--- a/nvflare/lighter/provision.py\n+++ b/nvflare/lighter/provision.py\n@@ -21,10 +21,9 @@\n import sys\n import webbrowser\n \n-import yaml\n-\n from nvflare.fuel.utils.class_utils import instantiate_class\n from nvflare.lighter.spec import Participant, Project, Provisioner\n+from nvflare.lighter.utils import load_yaml\n \n \n def main():\n@@ -77,7 +76,7 @@\n     project_full_path = os.path.join(current_path, project_file)\n     print(f\"Project yaml file: {project_full_path}.\")\n \n-    project_dict = yaml.load(open(project_full_path, \"r\"), Loader=yaml.Loader)\n+    project_dict = load_yaml(project_full_path)\n     api_version = project_dict.get(\"api_version\")\n     if api_version not in [3]:\n         raise ValueError(f\"API version expected 3 but found {api_version}\")\ndiff --git a/nvflare/lighter/utils.py b/nvflare/lighter/utils.py\n--- a/nvflare/lighter/utils.py\n+++ b/nvflare/lighter/utils.py\n@@ -46,7 +46,7 @@\n \n \n def load_yaml(file_name):\n-    return yaml.load(open(file_name, \"r\"), Loader=yaml.Loader)\n+    return yaml.safe_load(open(file_name, \"r\"))\n \n \n def sh_replace(src, mapping_dict):\n", "issue": "Yaml loader should be replaced by safe_loader or other more secure loader\nTo load yaml files from unknown source, we should avoid using yaml's loader.  A better way is to use either safe_loader or other mechanism.\n", "before_files": [{"content": "# Copyright (c) 2021-2022, NVIDIA CORPORATION.  All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom __future__ import absolute_import\n\nimport argparse\nimport os\nimport pathlib\nimport shutil\nimport sys\nimport webbrowser\n\nimport yaml\n\nfrom nvflare.fuel.utils.class_utils import instantiate_class\nfrom nvflare.lighter.spec import Participant, Project, Provisioner\n\n\ndef main():\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"-p\", \"--project_file\", type=str, default=\"project.yml\", help=\"file to describe FL project\")\n    parser.add_argument(\"-w\", \"--workspace\", type=str, default=\"workspace\", help=\"directory used by provision\")\n    parser.add_argument(\"-c\", \"--custom_folder\", type=str, default=\".\", help=\"additional folder to load python codes\")\n    parser.add_argument(\n        \"-u\",\n        \"--ui_tool\",\n        action=\"store_true\",\n        help=\"Run provisioning UI tool to generate project.yml file\",\n    )\n\n    args = parser.parse_args()\n\n    file_path = pathlib.Path(__file__).parent.absolute()\n    current_path = os.getcwd()\n    custom_folder_path = os.path.join(current_path, args.custom_folder)\n    sys.path.append(custom_folder_path)\n    print(\"Path list (sys.path) for python codes loading: {}\".format(sys.path))\n\n    # main project file\n    project_file = args.project_file\n    current_project_yml = os.path.join(current_path, \"project.yml\")\n    if len(sys.argv) == 1 and not os.path.exists(current_project_yml):\n        answer = input(\n            f\"No project.yml found in current folder.  Is it OK to generate one at {current_project_yml} for you? (y/N) \"\n        )\n        if answer.strip().upper() == \"Y\":\n            shutil.copyfile(os.path.join(file_path, \"project.yml\"), current_project_yml)\n            print(f\"{current_project_yml} was created.  Please edit it to fit your FL configuration.\")\n        exit(0)\n\n    if args.ui_tool:\n        ui_helper_path = os.path.join(file_path, \"provision_helper.html\")\n        ui_helper_url = f\"file://{ui_helper_path}\"\n        webbrowser.open_new_tab(ui_helper_url)\n        print(\n            \"\\n******\\n\"\n            \"Now launching provisioning UI tool.\\n\"\n            \"After generating project.yml in the browser and saving it to your local folder,\\n\"\n            \"please re-run provision with -p option, pointing to the generated project.yml, to generate all packages.\\n******\\n\"\n        )\n        exit(0)\n\n    workspace = args.workspace\n    workspace_full_path = os.path.join(current_path, workspace)\n\n    project_full_path = os.path.join(current_path, project_file)\n    print(f\"Project yaml file: {project_full_path}.\")\n\n    project_dict = yaml.load(open(project_full_path, \"r\"), Loader=yaml.Loader)\n    api_version = project_dict.get(\"api_version\")\n    if api_version not in [3]:\n        raise ValueError(f\"API version expected 3 but found {api_version}\")\n\n    project_name = project_dict.get(\"name\")\n    project_description = project_dict.get(\"description\", \"\")\n    participants = list()\n    for p in project_dict.get(\"participants\"):\n        participants.append(Participant(**p))\n    project = Project(name=project_name, description=project_description, participants=participants)\n\n    builders = list()\n    for b in project_dict.get(\"builders\"):\n        path = b.get(\"path\")\n        args = b.get(\"args\")\n        builders.append(instantiate_class(path, args))\n\n    provisioner = Provisioner(workspace_full_path, builders)\n\n    provisioner.provision(project)\n\n\nif __name__ == \"__main__\":\n    main()\n", "path": "nvflare/lighter/provision.py"}, {"content": "# Copyright (c) 2021-2022, NVIDIA CORPORATION.  All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport os\nimport random\nfrom base64 import b64encode\n\nimport yaml\nfrom cryptography.hazmat.primitives import hashes\nfrom cryptography.hazmat.primitives.asymmetric import padding\n\n\ndef generate_password():\n    s = \"abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n    passlen = 16\n    p = \"\".join(random.sample(s, passlen))\n    return p\n\n\ndef sign_all(content_folder, signing_pri_key):\n    signatures = dict()\n    for f in os.listdir(content_folder):\n        path = os.path.join(content_folder, f)\n        if os.path.isfile(path):\n            signature = signing_pri_key.sign(\n                data=open(path, \"rb\").read(),\n                padding=padding.PSS(\n                    mgf=padding.MGF1(hashes.SHA256()),\n                    salt_length=padding.PSS.MAX_LENGTH,\n                ),\n                algorithm=hashes.SHA256(),\n            )\n            signatures[f] = b64encode(signature).decode(\"utf-8\")\n    return signatures\n\n\ndef load_yaml(file_name):\n    return yaml.load(open(file_name, \"r\"), Loader=yaml.Loader)\n\n\ndef sh_replace(src, mapping_dict):\n    result = src\n    for k, v in mapping_dict.items():\n        result = result.replace(\"{~~\" + k + \"~~}\", str(v))\n    return result\n", "path": "nvflare/lighter/utils.py"}], "after_files": [{"content": "# Copyright (c) 2021-2022, NVIDIA CORPORATION.  All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom __future__ import absolute_import\n\nimport argparse\nimport os\nimport pathlib\nimport shutil\nimport sys\nimport webbrowser\n\nfrom nvflare.fuel.utils.class_utils import instantiate_class\nfrom nvflare.lighter.spec import Participant, Project, Provisioner\nfrom nvflare.lighter.utils import load_yaml\n\n\ndef main():\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"-p\", \"--project_file\", type=str, default=\"project.yml\", help=\"file to describe FL project\")\n    parser.add_argument(\"-w\", \"--workspace\", type=str, default=\"workspace\", help=\"directory used by provision\")\n    parser.add_argument(\"-c\", \"--custom_folder\", type=str, default=\".\", help=\"additional folder to load python codes\")\n    parser.add_argument(\n        \"-u\",\n        \"--ui_tool\",\n        action=\"store_true\",\n        help=\"Run provisioning UI tool to generate project.yml file\",\n    )\n\n    args = parser.parse_args()\n\n    file_path = pathlib.Path(__file__).parent.absolute()\n    current_path = os.getcwd()\n    custom_folder_path = os.path.join(current_path, args.custom_folder)\n    sys.path.append(custom_folder_path)\n    print(\"Path list (sys.path) for python codes loading: {}\".format(sys.path))\n\n    # main project file\n    project_file = args.project_file\n    current_project_yml = os.path.join(current_path, \"project.yml\")\n    if len(sys.argv) == 1 and not os.path.exists(current_project_yml):\n        answer = input(\n            f\"No project.yml found in current folder.  Is it OK to generate one at {current_project_yml} for you? (y/N) \"\n        )\n        if answer.strip().upper() == \"Y\":\n            shutil.copyfile(os.path.join(file_path, \"project.yml\"), current_project_yml)\n            print(f\"{current_project_yml} was created.  Please edit it to fit your FL configuration.\")\n        exit(0)\n\n    if args.ui_tool:\n        ui_helper_path = os.path.join(file_path, \"provision_helper.html\")\n        ui_helper_url = f\"file://{ui_helper_path}\"\n        webbrowser.open_new_tab(ui_helper_url)\n        print(\n            \"\\n******\\n\"\n            \"Now launching provisioning UI tool.\\n\"\n            \"After generating project.yml in the browser and saving it to your local folder,\\n\"\n            \"please re-run provision with -p option, pointing to the generated project.yml, to generate all packages.\\n******\\n\"\n        )\n        exit(0)\n\n    workspace = args.workspace\n    workspace_full_path = os.path.join(current_path, workspace)\n\n    project_full_path = os.path.join(current_path, project_file)\n    print(f\"Project yaml file: {project_full_path}.\")\n\n    project_dict = load_yaml(project_full_path)\n    api_version = project_dict.get(\"api_version\")\n    if api_version not in [3]:\n        raise ValueError(f\"API version expected 3 but found {api_version}\")\n\n    project_name = project_dict.get(\"name\")\n    project_description = project_dict.get(\"description\", \"\")\n    participants = list()\n    for p in project_dict.get(\"participants\"):\n        participants.append(Participant(**p))\n    project = Project(name=project_name, description=project_description, participants=participants)\n\n    builders = list()\n    for b in project_dict.get(\"builders\"):\n        path = b.get(\"path\")\n        args = b.get(\"args\")\n        builders.append(instantiate_class(path, args))\n\n    provisioner = Provisioner(workspace_full_path, builders)\n\n    provisioner.provision(project)\n\n\nif __name__ == \"__main__\":\n    main()\n", "path": "nvflare/lighter/provision.py"}, {"content": "# Copyright (c) 2021-2022, NVIDIA CORPORATION.  All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport os\nimport random\nfrom base64 import b64encode\n\nimport yaml\nfrom cryptography.hazmat.primitives import hashes\nfrom cryptography.hazmat.primitives.asymmetric import padding\n\n\ndef generate_password():\n    s = \"abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n    passlen = 16\n    p = \"\".join(random.sample(s, passlen))\n    return p\n\n\ndef sign_all(content_folder, signing_pri_key):\n    signatures = dict()\n    for f in os.listdir(content_folder):\n        path = os.path.join(content_folder, f)\n        if os.path.isfile(path):\n            signature = signing_pri_key.sign(\n                data=open(path, \"rb\").read(),\n                padding=padding.PSS(\n                    mgf=padding.MGF1(hashes.SHA256()),\n                    salt_length=padding.PSS.MAX_LENGTH,\n                ),\n                algorithm=hashes.SHA256(),\n            )\n            signatures[f] = b64encode(signature).decode(\"utf-8\")\n    return signatures\n\n\ndef load_yaml(file_name):\n    return yaml.safe_load(open(file_name, \"r\"))\n\n\ndef sh_replace(src, mapping_dict):\n    result = src\n    for k, v in mapping_dict.items():\n        result = result.replace(\"{~~\" + k + \"~~}\", str(v))\n    return result\n", "path": "nvflare/lighter/utils.py"}]}