
SpeechBrain < 1.1.1 checkpoint metadata RCE via unsafe PyYAML parsing of CKPT.yaml.
Severity: High, CVSS 4.0 8.7, CVSS 3.1 8.8 (assigned by VulnCheck, the CNA)
Vector (v4.0): CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Vector (v3.1): CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Affected: SpeechBrain < 1.1.1
Fixed in: 1.1.1 / commit 22a6166
CWE: CWE-502 (Deserialization of Untrusted Data)
Reported by: Sai Teja Erukude
CNA: VulnCheck
Published: August 27, 2026
SpeechBrain before 1.1.1 uses PyYAML's unsafe loader when parsing
checkpoint metadata during checkpoint recovery.
CKPT.yamlAn attacker who can supply or modify a SpeechBrain checkpoint directory can place
a malicious CKPT.yaml file inside a CKPT* checkpoint directory. When a victim
calls Checkpointer.recover_if_possible(), SpeechBrain lists checkpoint
candidates and parses every candidate metadata file with:
yaml.load(fi, Loader=yaml.Loader)
Because yaml.Loader supports Python object construction tags such as
!!python/object/apply, attacker-controlled checkpoint metadata can execute
Python code during checkpoint discovery.
The malicious checkpoint does not need to be selected or restored. Code execution occurs while SpeechBrain is enumerating checkpoint candidates.
An attacker may execute arbitrary Python code in the context of the Python process running SpeechBrain.
This can affect workflows where users download, unpack, resume, or run training/inference from untrusted checkpoint directories, model artifacts, or archives.
Depending on the hosting process, this may allow:
The affected component is SpeechBrain's checkpoint recovery/listing flow:
Checkpointer.recover_if_possible()
-> list_checkpoints()
-> _construct_checkpoint_objects()
During checkpoint listing, SpeechBrain scans child directories named CKPT* that
contain CKPT.yaml. Each candidate metadata file is parsed before final
checkpoint selection.
The unsafe parse happens in speechbrain.utils.checkpoints.checkpoints.py:
meta = yaml.load(fi, Loader=yaml.Loader)
The PoC creates two checkpoints:
CKPT+poisoned-metadata: an older malicious checkpoint whose CKPT.yaml
contains a PyYAML object-apply payload.CKPT+benign-newer: a newer benign checkpoint that should be selected by
recency.The benign checkpoint is selected, but the malicious checkpoint metadata still executes during candidate listing. This demonstrates metadata parse-time code execution independent of checkpoint restoration.
package_builder.py creates the attacker-controlled
checkpoint layout.
run_poc.py runs the validation, calls
Checkpointer.recover_if_possible(), and prints execution evidence.
Run in a local test environment only:
python -m venv .venv
.venv\Scripts\activate
python -m pip install -r requirements.txt
python -B run_poc.py
Expected evidence on vulnerable versions:
speechbrain_version: 1.1.0
installed_package: True
recovery_error: None
benign_checkpoint_selected: True
marker_before_recovery: False
marker_after_recovery: True
marker_contents:
speechbrain_checkpoint_yaml_loader_rce_triggered
success: True
The important evidence is that benign_checkpoint_selected: True and
marker_after_recovery: True appear together. This shows that the malicious
older checkpoint was not selected for recovery, but its metadata was still parsed
and executed while SpeechBrain listed checkpoint candidates.
The payload is intentionally harmless. It only writes this local marker string:
speechbrain_checkpoint_yaml_loader_rce_triggered
It does not spawn a shell, connect to a network service, read secrets, delete data, or modify files outside the PoC directory.
Upgrade to SpeechBrain 1.1.1 or later.
The durable code fix is to use PyYAML's safe loader for checkpoint metadata:
yaml.safe_load(fi)
or:
yaml.load(fi, Loader=yaml.SafeLoader)
Checkpoint metadata only needs scalar values such as unixtime and
end-of-epoch, so Python object construction should not be enabled for this
parse path.
If an immediate patch or upgrade is not available:
CKPT.yaml.Discovered and reported by Sai Teja Erukude, coordinated through VulnCheck.
exploit_walkthrough.md