Skip to content

Commit f2c9b16

Browse files
committed
Update app.py
1 parent 5d1eb66 commit f2c9b16

File tree

1 file changed

+35
-6
lines changed

1 file changed

+35
-6
lines changed

app.py

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
from dotenv import load_dotenv
1616
from celery.result import AsyncResult
1717
from celery_worker import celery, process_tts_request
18+
from werkzeug.utils import secure_filename
19+
import os.path
1820

1921
# Configure logging
2022
logging.basicConfig(
@@ -75,9 +77,20 @@ def serve_static_files(path):
7577
if path == '':
7678
return send_from_directory('static', 'index.html')
7779

78-
full_path = Path('static') / path
80+
# Secure the filename and prevent path traversal
81+
secure_path = secure_filename(path)
82+
if not secure_path or secure_path != path:
83+
return "Invalid path", 400
7984

80-
if full_path.exists():
85+
# Normalize and validate the path
86+
base_path = os.path.abspath('static')
87+
full_path = os.path.normpath(os.path.join(base_path, secure_path))
88+
89+
# Ensure the path is within the static directory
90+
if not full_path.startswith(base_path):
91+
return "Invalid path", 400
92+
93+
if os.path.exists(full_path):
8194
# Determine content type
8295
content_type = {
8396
'.html': 'text/html',
@@ -87,7 +100,7 @@ def serve_static_files(path):
87100
'.jpg': 'image/jpeg',
88101
'.gif': 'image/gif',
89102
'.ico': 'image/x-icon'
90-
}.get(full_path.suffix, 'application/octet-stream')
103+
}.get(os.path.splitext(full_path)[1], 'application/octet-stream')
91104

92105
return send_file(full_path, mimetype=content_type)
93106

@@ -236,8 +249,24 @@ def voice_sample(voice):
236249
"error": "Voice parameter is required"
237250
}), 400
238251

239-
sample_path = VOICE_SAMPLES_DIR / f"{voice}_sample.mp3"
240-
if not sample_path.exists():
252+
# Secure the voice parameter and prevent path traversal
253+
secure_voice = secure_filename(voice)
254+
if not secure_voice or secure_voice != voice:
255+
return jsonify({
256+
"error": "Invalid voice parameter"
257+
}), 400
258+
259+
# Normalize and validate the path
260+
base_path = os.path.abspath(VOICE_SAMPLES_DIR)
261+
sample_path = os.path.normpath(os.path.join(base_path, f"{secure_voice}_sample.mp3"))
262+
263+
# Ensure the path is within the voice samples directory
264+
if not sample_path.startswith(base_path):
265+
return jsonify({
266+
"error": "Invalid path"
267+
}), 400
268+
269+
if not os.path.exists(sample_path):
241270
return jsonify({
242271
"error": f"Sample not found for voice: {voice}"
243272
}), 404
@@ -246,7 +275,7 @@ def voice_sample(voice):
246275
sample_path,
247276
mimetype="audio/mpeg",
248277
as_attachment=False,
249-
download_name=f"{voice}_sample.mp3"
278+
download_name=f"{secure_voice}_sample.mp3"
250279
)
251280

252281
except Exception as e:

0 commit comments

Comments
 (0)