Coordinated Disclosure Timeline
- 2024-12-11: Reported the vulnerabilities via PVR.
- 2025-01-07: Followed up asking if the vulnerabilities have been fixed.
- 2025-01-22: Reached out again.
- 2023-01-27: The maintainer commented on an issue in another repository, and from there I asked them to check PVR.
- 2025-01-28: Received a reply in PVR asking about the impact. Explained the impact of GHSL-2024-354 and GHSL-2024-341 through GHSL-2024-353.
- 2025-02-01: The unsafe deserialization vulnerabilities (GHSL-2024-345 through GHSL-2024-348) were issued a fix.
- 2025-02-03: Reached out explaining the next steps in the disclosure process.
- 2025-02-10: Reached out with a reminder about the 90d disclosure deadline.
- 2025-03-07: Gave a notice about the deadline.
- 2025-03-10: Final notice about the deadline, and heads-up that details will be published by the end of the week.
Summary
Applio 3.2.7 is vulnerable to unsafe deserialization, SSRFs and arbitrary file writes, arbitrary file read and arbitrary file removal.
Project
Applio
Tested Version
Details
Issue 1: SSRF and file write in model_download.py line 143 (GHSL-2024-341
)
These endpoints take a user-supplied URL:
- download.py on line 194
- routes.py which later is used to make an HTTP GET request to arbitrary destinations in model_download.py on line 143 and then download arbitrary files from the URL on lines 147-148, which leads to blind server-side request forgery and file write.
Similar issues exist for GHSL-2024-342
and GHSL-2024-343
.
model_download.py
elif "cdn.discordapp.com" in url:
file = requests.get(url)
os.chdir(zips_path)
if file.status_code == 200:
name = url.split("/")
with open(os.path.join(name[-1]), "wb") as newfile:
newfile.write(file.content)
This issue was found with help of CodeQL SSRF query.
Impact
The blind server-side request forgery allows for sending requests on behalf of applio server and can be leveraged to probe for other vulnerabilities on the server itself or on other back-end systems on the internal network, that the applio server can reach.
The blind SSRF can be coupled with the arbitrary file read GHSL-2024-351, to read files from hosts on the internal network, that the applio server can reach, which would make it a full SSRF.
The file write allows for writing files on the server, which can be coupled with other vulnerabilities, for example one of the unsafe deserialisations, to achieve remote code execution on the applio server.
Issue 2: SSRF and file write in model_download.py line 156 (GHSL-2024-342
)
Similarly to GHSL-2024-341
and GHSL-2024-343
, the two endpoints take a user-supplied URL:
- download.py on line 194
- routes.py which later is used to make an HTTP GET request to arbitrary destinations in model_download.py on line 156 and then download arbitrary files from the URL on lines 169-171, which leads to blind server-side request forgery and file write.
elif "/blob/" in url or "/resolve/" in url:
os.chdir(zips_path)
if "/blob/" in url:
url = url.replace("/blob/", "/resolve/")
response = requests.get(url, stream=True)
Impact
The blind server-side request forgery allows for sending requests on behalf of applio server and can be leveraged to probe for other vulnerabilities on the server itself or on other back-end systems on the internal network, that the applio server can reach.
The file write allows for writing files on the server, which can be coupled with other vulnerabilities, for example one of the unsafe deserialisations, to achieve remote code execution on the applio server.
Issue 3: SSRF and file write in model_download.py line 240 (GHSL-2024-343
)
Similarly to GHSL-2024-341
and GHSL-2024-342
, the two endpoints take a user-supplied URL:
- download.py on line 194
- routes.py which later is used to make an HTTP GET request to arbitrary destinations in model_download.py on line 240 and download arbitrary files, which leads to blind server-side request forgery and file write.
Similar issues exist for GHSL-2024-341
and GHSL-2024-342
.
model_download.py
else:
try:
os.chdir(zips_path)
wget.download(url)
This issue was found with help of CodeQL SSRF query.
Impact
The blind server-side request forgery allows for sending requests on behalf of applio server and can be leveraged to probe for other vulnerabilities on the server itself or on other back-end systems on the internal network, that the applio server can reach.
The blind SSRF can be coupled with the arbitrary file read GHSL-2024-351, to read files from hosts on the internal network, that the applio server can reach, which would make it a full SSRF.
The file write allows for writing files on the server, which can be coupled with other vulnerabilities, for example one of the unsafe deserialisations, to achieve remote code execution on the applio server.
Issue 4: SSRF in model_download.py line 195 (GHSL-2024-344
)
Similarly to the above issues, the two endpoints take a user-supplied URL:
- download.py on line 194
- routes.py which later is used to make an HTTP GET request to arbitrary destinations in model_download.py on line 195 which leads to blind server-side request forgery.
elif "/tree/main" in url:
os.chdir(zips_path)
response = requests.get(url)
This issue was found with help of CodeQL SSRF query.
Impact
The blind server-side request forgery allows for sending requests on behalf of applio server and can be leveraged to probe for other vulnerabilities on the server itself or on other back-end systems on the internal network, that the applio server can reach.
The blind SSRF can be coupled with the arbitrary file read GHSL-2024-351, to read files from hosts on the internal network, that the applio server can reach, which would make it a full SSRF.
Issue 5: Unsafe deserialization in infer.py (GHSL-2024-345
)
model_file
in inference.py as well asmodel_file
in tts.py take user-supplied input (e.g. a path to a model) and pass that value to therun_infer_script
and later toconvert_audio
and thenget_vc
function, which loads that model withtorch.load
in infer.py line 464, which is vulnerable to unsafe deserialization.
Impact
The issue can lead to remote code execution.
Issue 6: Unsafe deserialization in model_blender.py line 20 and 21 (GHSL-2024-346
)
model_fusion_a
and model_fusion_b
from voice_blender.py take user-supplied input (e.g. a path to a model) and pass that value to the run_model_blender_script
and later to model_blender
function, which loads these two models with torch.load
in `model_blender.py on lines 20-21, which is vulnerable to unsafe deserialization.
Impact
The issue can lead to remote code execution.
Issue 7: Unsafe deserialization in model_information.py (GHSL-2024-347
)
model_name
in model_information.py
takes user-supplied input (e.g. a path to a model) and pass that value to the run_model_information_script
and later to model_information
function, which loads that model with torch.load
in rvc/train/process/model_information.py on line 16, which is vulnerable to unsafe deserialization.
Impact
The issue can lead to remote code execution.
Issue 8: Unsafe deserialization in inference.py (GHSL-2024-348
)
model_file
in inference.py as well asmodel_file
in tts.py take user-supplied input (e.g. a path to a model) and pass that value to thechange_choices
and later toget_speakers_id
function, which loads that model withtorch.load
in inference.py line 325, which is vulnerable to unsafe deserialization.
Impact
The issue can lead to remote code execution.
Issue 9: Arbitrary file write in inference.py (GHSL-2024-349
)
The three endpoints:
folder_name_input
,bin_file_upload
,config_file_upload
ininference.py
lines 989-1002folder_name_input_batch
,bin_file_upload_batch
andconfig_file_upload_batch
ininference.py
line 1632-45folder_name_input
,bin_file_upload
,config_file_upload
intts.py
lines 309-322
take arbitrary user input in folder_name_input
and files in bin_file_upload
, config_file_upload
and pass that input to create_folder_and_move_files
function in inference.py. folder_name_input
is used to construct a path on line 295
and then copy the uploaded files on lines 300 and 304. There is no check if the file is copied the expected, static custom_embedder_root
path, which allows attackers to write arbitrary file on applio server, as long the user running the application has write access to a given path.
def create_folder_and_move_files(folder_name, bin_file, config_file):
if not folder_name:
return "Folder name must not be empty."
folder_name = os.path.join(custom_embedder_root, folder_name)
os.makedirs(folder_name, exist_ok=True)
if bin_file:
bin_file_path = os.path.join(folder_name, os.path.basename(bin_file))
shutil.copy(bin_file, bin_file_path)
if config_file:
config_file_path = os.path.join(folder_name, os.path.basename(config_file))
shutil.copy(config_file, config_file_path)
This issue was found with help of CodeQL path injection query.
Impact
This issue may lead to writing arbitrary files on the applio server. It can also be used in conjunction with any of the unsafe deserialisations to achieve remote code execution.
Issue 10: Arbitrary file write in train.py (GHSL-2024-350
)
This issue is very similar to GHSL-2024-349. The code for the two issues is almost the same, but the happen in different files.
folder_name_input
, bin_file_upload
, config_file_upload
in tabs/train/train.py take arbitrary user input in folder_name_input
and files in bin_file_upload
, config_file_upload
and pass that input to create_folder_and_move_files
function in tabs/train/train.py. folder_name_input
is used to construct a path on line 295
and then copy the uploaded files. There is no check if the file is copied the expected, static custom_embedder_root
path, which allows attackers to write arbitrary file on applio server, as long the user running the application has write access to a given path.
def create_folder_and_move_files(folder_name, bin_file, config_file):
if not folder_name:
return "Folder name must not be empty."
folder_name = os.path.join(custom_embedder_root, folder_name)
os.makedirs(folder_name, exist_ok=True)
if bin_file:
bin_file_path = os.path.join(folder_name, os.path.basename(bin_file))
shutil.copy(bin_file, bin_file_path)
if config_file:
config_file_path = os.path.join(folder_name, os.path.basename(config_file))
shutil.copy(config_file, config_file_path)
This issue was found with help of CodeQL path injection query.
Impact
This issue may lead to writing arbitrary files on the applio server. It can also be used in conjunction with any of the unsafe deserialisations to achieve remote code execution.
Issue 11: Arbitrary file read in train.py export_pth
function (GHSL-2024-351
)
pth_dropdown_export
in tabs/train/train.py takes arbitrary user input and passes it to export_pth
function, which checks that the file exists, and returns it to user. Since there are no restrictions on which files it returns, this leads to arbitrary file read on files on the applio server.
def export_pth(pth_path):
if pth_path and os.path.exists(pth_path):
return pth_path
This issue was found with help of CodeQL path injection query.
Impact
This issue may lead to reading arbitrary files on the applio server. It can also be used in conjunction with any of the blind SSRF to read files from servers on the internal network that the applio server has access to.
Issue 12: Arbitrary file read in train.py export_index
function (GHSL-2024-352
)
index_dropdown_export
in tabs/train/train.py takes arbitrary user input and passes it to export_index
function, which checks that the file exists, and returns it to user. Since there are no restrictions on which files it returns, this leads to arbitrary file read on files on the applio server.
def export_index(index_path):
if index_path and os.path.exists(index_path):
return index_path
return None
This issue was found with help of CodeQL path injection query.
Impact
This issue may lead to reading arbitrary files on the applio server. It can also be used in conjunction with any of the blind SSRF to read files from servers on the internal network that the applio server has access to.
Issue 13: Arbitrary file removal in core.py (GHSL-2024-353
)
output_tts_path
in tts.py takes arbitrary user input and passes it to run_tts_script
function in core.py, which checks if the path in output_tts_path
exists, and if yes, removes that path, which leads to arbitrary file removal.
if os.path.exists(output_tts_path):
os.remove(output_tts_path)
Impact
This issue may lead to reading arbitrary files on the applio server. It can also be used in conjunction with any of the blind SSRF to read files from servers on the internal network that the applio server has access to.
CVE
- CVE-2025-27774 - GHSL-2024-341
- CVE-2025-27775 - GHSL-2024-342
- CVE-2025-27776 - GHSL-2024-343
- CVE-2025-27777 - GHSL-2024-344
- CVE-2025-27778 - GHSL-2024-345
- CVE-2025-27779 - GHSL-2024-346
- CVE-2025-27780 - GHSL-2024-347
- CVE-2025-27781 - GHSL-2024-348
- CVE-2025-27782 - GHSL-2024-349
- CVE-2025-27783 - GHSL-2024-350
- CVE-2025-27784 - GHSL-2024-351
- CVE-2025-27785 - GHSL-2024-352
- CVE-2025-27786 - GHSL-2024-353
Credit
These issues were discovered and reported by GHSL team member @sylwia-budzynska (Sylwia Budzynska).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2024-341
, GHSL-2024-342
, GHSL-2024-343
, GHSL-2024-344
, GHSL-2024-345
, GHSL-2024-346
, GHSL-2024-347
, GHSL-2024-348
, GHSL-2024-349
, GHSL-2024-350
, GHSL-2024-351
, GHSL-2024-352
, or GHSL-2024-353
in any communication regarding these issues.