Skip to content

CWE-22 Path Traversal in load_grammar() — arbitrary file read without authentication

High
oobabooga published GHSA-hqg5-487v-5mc6 Apr 3, 2026

Package

pip text-generation-webui (pip)

Affected versions

< 4.3

Patched versions

4.3

Description

Summary

An unauthenticated path traversal vulnerability in load_grammar() allows reading any file on the server filesystem with no extension restriction.
Gradio does not server-side validate dropdown values, so an attacker can POST directory traversal payloads (e.g., ../../../etc/passwd) via the API and receive the full file contents in the response.

Details

The vulnerable code is in modules/ui_parameters.py at lines 137-142:

def load_grammar(name):
    p = shared.user_data_dir / 'grammars' / name
    if p.exists():
        return open(p, 'r', encoding='utf-8').read()
    else:
        return ''

The name parameter comes from a Gradio Dropdown component.
Gradio does not validate that the submitted value matches the declared choices, so any string is accepted via the /gradio_api/call/load_grammar endpoint.
There is no call to os.path.basename(), sanitize_filename(), or any other path validation.
Unlike load_preset() or load_prompt(), this function does not append a file extension, meaning any file type can be read.

PoC

  1. Clone the repository and install dependencies.
  2. Start the server: python server.py --listen-port 7861
  3. Send a crafted API request:
curl -X POST http://127.0.0.1:7861/gradio_api/call/load_grammar \
  -H "Content-Type: application/json" \
  -d '{"data": ["../../../etc/passwd"]}'

poc.zip

  1. Fetch the result using the returned event_id:
curl http://127.0.0.1:7861/gradio_api/call/load_grammar/<event_id>
  1. The full contents of /etc/passwd are returned in the response.

I verified this by cloning the repository at current HEAD, extracting the verbatim load_grammar() function, and confirming that /etc/passwd (3,192 bytes, 55 lines) and ~/.ssh/id_rsa (3,381 bytes) are both exfiltrated in full.

Impact

Any file readable by the server process can be exfiltrated by an unauthenticated attacker.
This includes /etc/passwd, SSH private keys, .env files, API tokens, and application configuration.
The default deployment has no authentication (--gradio-auth is optional).
Cloud deployments commonly use --listen or --share, making the server remotely accessible.
The same vulnerability pattern exists in load_preset() (presets.py), load_prompt() (prompts.py), and load_template() (training.py), reported separately.

Remediation: apply os.path.basename(name) 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)

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
None
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

CVE ID

CVE-2026-35485

Weaknesses

Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory. Learn more on MITRE.

Credits