Skip to content

Commit d9a8337

Browse files
authored
Merge pull request #315 from GaneshPatil7517/fix/path-traversal-download
2 parents b289c32 + 7ad1c25 commit d9a8337

1 file changed

Lines changed: 28 additions & 4 deletions

File tree

fri/server/main.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from flask import Flask, request, jsonify, send_file, send_from_directory
1+
from flask import Flask, request, jsonify, send_file, send_from_directory, abort
22
from werkzeug.utils import secure_filename
33
import xml.etree.ElementTree as ET
44
import os
@@ -330,15 +330,39 @@ def contribute():
330330
def download(dir):
331331
download_file = request.args.get('fetch')
332332
sub_folder = request.args.get('fetchDir')
333+
334+
if not download_file:
335+
abort(400, description="Missing file parameter")
336+
337+
# Normalize the requested file path
338+
safe_path = os.path.normpath(download_file)
339+
340+
# Prevent absolute paths
341+
if os.path.isabs(safe_path):
342+
abort(400, description="Invalid file path")
343+
344+
# Prevent directory traversal
345+
if ".." in safe_path.split(os.sep):
346+
abort(400, description="Directory traversal attempt detected")
347+
333348
dirname = secure_filename(dir) + "/" + secure_filename(sub_folder)
334-
directory_name = os.path.abspath(os.path.join(concore_path, dirname))
349+
concore_real = os.path.realpath(concore_path)
350+
directory_name = os.path.realpath(os.path.join(concore_real, dirname))
351+
if not directory_name.startswith(concore_real + os.sep):
352+
abort(403, description="Access denied")
335353
if not os.path.exists(directory_name):
336354
resp = jsonify({'message': 'Directory not found'})
337355
resp.status_code = 400
338356
return resp
357+
358+
# Ensure final resolved path is within the intended directory, resolving symlinks
359+
full_path = os.path.realpath(os.path.join(directory_name, safe_path))
360+
if not full_path.startswith(directory_name + os.sep):
361+
abort(403, description="Access denied")
362+
339363
try:
340-
return send_from_directory(directory_name, download_file, as_attachment=True)
341-
except:
364+
return send_from_directory(directory_name, safe_path, as_attachment=True)
365+
except Exception:
342366
resp = jsonify({'message': 'file not found'})
343367
resp.status_code = 400
344368
return resp

0 commit comments

Comments
 (0)