π Bug
Loading a model can execute arbitrary code. read_yaml() in utils/infer_utils.py (~line 319) parses a model's
config.yaml with PyYAML's UNSAFE full loader β yaml.load(f, Loader=yaml.Loader). yaml.Loader constructs arbitrary
Python objects from YAML tags (e.g. an os.system apply tag), so a crafted config.yaml runs shell commands at parse
time; when the model is loaded, before/independent of the ONNX weights.
This is deserialization of untrusted data (CWE-502): a user who loads a shared or attacker-published SenseVoice model gets arbitrary code execution.
I'm keeping this public report to the diagnosis and withholding a working proof-of-concept, since the code is
currently unpatched. Full reproduction available privately if you enable private vulnerability reporting or share a contact email.
To Reproduce
Exact command (benign, this is the load path that reaches the sink):
- Run:
python -c "from model import SenseVoiceSmallONNX; SenseVoiceSmallONNX('<model_dir_or_downloaded_model>')"
(any public entrypoint that loads the ONNX model calls read_yaml() on its config.yaml)
- read_yaml() parses config.yaml via yaml.load(f, Loader=yaml.Loader). If that config.yaml contains a
Python-object YAML tag, the tag executes at parse time.
The malicious config.yaml / turnkey PoC is withheld here to avoid publishing a working exploit before a fix. I'll
share the full step-by-step reproduction privately.
Code sample
The sink, from the current source (utils/infer_utils.py ~L319):
def read_yaml(yaml_path):
with open(str(yaml_path), "rb") as f:
data = yaml.load(f, Loader=yaml.Loader) # <-- unsafe: executes Python-object YAML tags
return data
Reached on the public load path when the ONNX model is loaded, e.g. SenseVoiceSmallONNX(model_dir), where model_dir may be a downloaded/attacker-supplied bundle whose config.yaml is untrusted. A config.yaml carrying a Python-object tag runs code inside read_yaml(). (Payload withheld.)
Expected behavior
Loading a model configuration should only read data. Parsing a model's config.yaml must never construct arbitrary Python objects or execute code.
Environment
- OS: platform-independent (Python/PyYAML issue; reproduced on Linux)
- FunASR Version: N/A β this is SenseVoice (all versions, current main)
- ModelScope Version: N/A (issue is in the config parser, independent of model source)
- PyTorch Version: N/A (weights are ONNX; sink fires before/independent of weight load)
- How you installed: source / the SenseVoice ONNX runtime
- Python version: 3.x
- GPU: N/A (parse-time issue, device-independent)
- CUDA/cuDNN version: N/A
- Docker version: N/A
- Any other relevant information: sink at utils/infer_utils.py read_yaml(), yaml.load(f, Loader=yaml.Loader)
Additional context
Suggested fix (one line): replace Loader=yaml.Loader with Loader=yaml.SafeLoader in utils/infer_utils.py
read_yaml() β configs are plain mappings/lists/scalars, so it's a drop-in with no functional change.
Severity CVSS 3.1 8.4
(AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H); CVE requested (coordinated disclosure).
The same read_yaml is vendored from modelscope/FunASR, reported separately.
π Bug
Loading a model can execute arbitrary code. read_yaml() in utils/infer_utils.py (~line 319) parses a model's
config.yaml with PyYAML's UNSAFE full loader β yaml.load(f, Loader=yaml.Loader). yaml.Loader constructs arbitrary
Python objects from YAML tags (e.g. an os.system apply tag), so a crafted config.yaml runs shell commands at parse
time; when the model is loaded, before/independent of the ONNX weights.
This is deserialization of untrusted data (CWE-502): a user who loads a shared or attacker-published SenseVoice model gets arbitrary code execution.
I'm keeping this public report to the diagnosis and withholding a working proof-of-concept, since the code is
currently unpatched. Full reproduction available privately if you enable private vulnerability reporting or share a contact email.
To Reproduce
Exact command (benign, this is the load path that reaches the sink):
python -c "from model import SenseVoiceSmallONNX; SenseVoiceSmallONNX('<model_dir_or_downloaded_model>')"
(any public entrypoint that loads the ONNX model calls read_yaml() on its config.yaml)
Python-object YAML tag, the tag executes at parse time.
The malicious config.yaml / turnkey PoC is withheld here to avoid publishing a working exploit before a fix. I'll
share the full step-by-step reproduction privately.
Code sample
The sink, from the current source (utils/infer_utils.py ~L319):
def read_yaml(yaml_path):
with open(str(yaml_path), "rb") as f:
data = yaml.load(f, Loader=yaml.Loader) # <-- unsafe: executes Python-object YAML tags
return data
Reached on the public load path when the ONNX model is loaded, e.g. SenseVoiceSmallONNX(model_dir), where model_dir may be a downloaded/attacker-supplied bundle whose config.yaml is untrusted. A config.yaml carrying a Python-object tag runs code inside read_yaml(). (Payload withheld.)
Expected behavior
Loading a model configuration should only read data. Parsing a model's config.yaml must never construct arbitrary Python objects or execute code.
Environment
Additional context
Suggested fix (one line): replace Loader=yaml.Loader with Loader=yaml.SafeLoader in utils/infer_utils.py
read_yaml() β configs are plain mappings/lists/scalars, so it's a drop-in with no functional change.
Severity CVSS 3.1 8.4
(AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H); CVE requested (coordinated disclosure).
The same read_yaml is vendored from modelscope/FunASR, reported separately.