Summary
An unauthenticated path traversal vulnerability in load_template() allows reading files with .jinja, .jinja2, .yaml, or .yml extensions from anywhere on the server filesystem.
For .jinja files the content is returned verbatim; for .yaml files a parsed key is extracted.
Details
The vulnerable code is in modules/training.py at lines 228-237:
def load_template(name):
path = shared.user_data_dir / 'instruction-templates'
for ext in ['jinja', 'jinja2', 'yaml', 'yml']:
filepath = path / f'{name}.{ext}'
if filepath.exists():
if ext in ['jinja', 'jinja2']:
return filepath.read_text(encoding='utf-8')
else:
data = yaml.safe_load(filepath.read_text(encoding='utf-8'))
return data.get('instruction_template', '')
The name parameter comes from a Gradio Dropdown and is not sanitized.
Notably, clean_path() exists in the same file at line 190 (replaces .. with _) and is applied to lora_name in do_train(), but it is not applied to name in load_template().
The four-extension iteration broadens the attack surface compared to the other path traversal findings.
PoC
- Clone the repository and start the server.
- Send a crafted API request with a traversal payload as the template name.
- The server iterates over four extensions, opens the first matching file, and returns its content.
I verified this by cloning the repository, running the verbatim load_template() function with traversal payloads, and confirming both .yaml parsed content and .jinja verbatim content leakage from outside the instruction-templates directory.
poc.zip
Impact
Any .jinja, .jinja2, .yaml, or .yml file readable by the server process can be exfiltrated.
No authentication required by default.
The clean_path() fix already exists in the codebase but is not applied to this function.
Remediation: apply os.path.basename(name) or the existing clean_path() before path construction.
We believe this qualifies as a valid security issue.
If you agree, we'd appreciate the following credit on the CVE:
Reported by Woohyun Choi, Sunwoo Lee, and Seunghyun Yoon (Korea Institute of Energy Technology, KENTECH)
Summary
An unauthenticated path traversal vulnerability in
load_template()allows reading files with.jinja,.jinja2,.yaml, or.ymlextensions from anywhere on the server filesystem.For
.jinjafiles the content is returned verbatim; for.yamlfiles a parsed key is extracted.Details
The vulnerable code is in
modules/training.pyat lines 228-237:The
nameparameter comes from a Gradio Dropdown and is not sanitized.Notably,
clean_path()exists in the same file at line 190 (replaces..with_) and is applied tolora_nameindo_train(), but it is not applied tonameinload_template().The four-extension iteration broadens the attack surface compared to the other path traversal findings.
PoC
I verified this by cloning the repository, running the verbatim
load_template()function with traversal payloads, and confirming both.yamlparsed content and.jinjaverbatim content leakage from outside the instruction-templates directory.poc.zip
Impact
Any
.jinja,.jinja2,.yaml, or.ymlfile readable by the server process can be exfiltrated.No authentication required by default.
The
clean_path()fix already exists in the codebase but is not applied to this function.Remediation: apply
os.path.basename(name)or the existingclean_path()before path construction.We believe this qualifies as a valid security issue.
If you agree, we'd appreciate the following credit on the CVE:
Reported by Woohyun Choi, Sunwoo Lee, and Seunghyun Yoon (Korea Institute of Energy Technology, KENTECH)