From 9b6644967daa62580a65867b25cfa6ee2015fc71 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 31 Jan 2026 07:30:39 +0000 Subject: [PATCH 1/3] Initial plan From 2c8fc497d1e2d4c62d7d259e3e4b387300598b82 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 31 Jan 2026 07:34:48 +0000 Subject: [PATCH 2/3] Fix multiple issues: security vulnerabilities, HTML syntax, missing blueprint, unused imports Co-authored-by: amitdevx <110670491+amitdevx@users.noreply.github.com> --- FileFlow/backend/api/files.py | 17 +++++++-- FileFlow/backend/app.py | 9 ++--- FileFlow/backend/config.py | 4 +- .../backend/services/compression_service.py | 34 ++++++++++++++++- FileFlow/frontend/js/app.js/auth.js | 0 .../js/{app.js => }/file_management.js | 0 FileFlow/frontend/templates/dashboard.html | 6 +-- FileFlow/start.sh | 13 ++++--- READMED.md | 38 ------------------- start.sh | 7 +++- 10 files changed, 65 insertions(+), 63 deletions(-) delete mode 100644 FileFlow/frontend/js/app.js/auth.js rename FileFlow/frontend/js/{app.js => }/file_management.js (100%) delete mode 100644 READMED.md diff --git a/FileFlow/backend/api/files.py b/FileFlow/backend/api/files.py index bb2750b5..e2f1cdb1 100644 --- a/FileFlow/backend/api/files.py +++ b/FileFlow/backend/api/files.py @@ -3,8 +3,10 @@ from werkzeug.utils import secure_filename try: from backend.models.database import db, File + from backend.utils.validators import Validators except ImportError: from models.database import db, File + from utils.validators import Validators from pathlib import Path files_bp = Blueprint('files_bp', __name__) @@ -111,11 +113,18 @@ def rename_file(file_id): new_name = data.get('new_name') if not new_name: - abort(400) - - file_to_rename.filename = new_name + abort(400, description="New name is required") + + # Validate and sanitize the filename + if not Validators.is_valid_filename(new_name): + abort(400, description="Invalid filename") + + # Sanitize the filename to remove any dangerous characters + sanitized_name = Validators.sanitize_filename(new_name) + + file_to_rename.filename = sanitized_name db.session.commit() - return jsonify({'success': True, 'new_name': new_name}) + return jsonify({'success': True, 'new_name': sanitized_name}) @files_bp.route('/move_file/', methods=['POST']) @login_required diff --git a/FileFlow/backend/app.py b/FileFlow/backend/app.py index 5f390db2..259fccf5 100644 --- a/FileFlow/backend/app.py +++ b/FileFlow/backend/app.py @@ -179,12 +179,6 @@ def open_folder(folder_id): app.logger.error(f"Error in open_folder: {str(e)}") abort(500, description="Error occurred while opening folder") -from datetime import datetime - -# ... (rest of the imports) - -# ... (rest of the code) - @app.route('/create_folder', methods=['POST']) @login_required def create_folder(): @@ -280,18 +274,21 @@ def init_db_command(): from backend.api.folders import folders_bp from backend.api.search import search_bp from backend.api.upload import upload_bp + from backend.api.compression import compression_bp except ImportError: from api.auth import auth_bp from api.files import files_bp from api.folders import folders_bp from api.search import search_bp from api.upload import upload_bp + from api.compression import compression_bp app.register_blueprint(files_bp) app.register_blueprint(folders_bp) app.register_blueprint(search_bp) app.register_blueprint(upload_bp) app.register_blueprint(auth_bp) +app.register_blueprint(compression_bp) import threading try: diff --git a/FileFlow/backend/config.py b/FileFlow/backend/config.py index 979edb19..0ec3eef2 100644 --- a/FileFlow/backend/config.py +++ b/FileFlow/backend/config.py @@ -1,8 +1,8 @@ import os class Config: - SECRET_KEY = os.urandom(24) - SQLALCHEMY_DATABASE_URI = 'sqlite:///fileflow.db' + SECRET_KEY = os.environ.get('SECRET_KEY') or os.urandom(24) + SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///fileflow.db' SQLALCHEMY_TRACK_MODIFICATIONS = False UPLOAD_FOLDER = 'user_files' MAX_CONTENT_LENGTH = 16 * 1024 * 1024 # 16MB max file upload \ No newline at end of file diff --git a/FileFlow/backend/services/compression_service.py b/FileFlow/backend/services/compression_service.py index 7b1799ab..a9690753 100644 --- a/FileFlow/backend/services/compression_service.py +++ b/FileFlow/backend/services/compression_service.py @@ -4,6 +4,24 @@ from pathlib import Path class CompressionService: + @staticmethod + def _is_safe_path(base_path, target_path): + """Check if target path is within base path (prevents directory traversal)""" + try: + base = Path(base_path).resolve() + target = Path(target_path).resolve() + return target.is_relative_to(base) + except (ValueError, RuntimeError): + return False + + @staticmethod + def _safe_extract_member(archive_path, member_name, extract_to): + """Validate that extracted file stays within extract_to directory""" + target_path = Path(extract_to) / member_name + if not CompressionService._is_safe_path(extract_to, target_path): + raise ValueError(f"Attempted path traversal in archive: {member_name}") + return True + @staticmethod def create_zip(file_paths, archive_path, password=None): with zipfile.ZipFile(archive_path, 'w', zipfile.ZIP_DEFLATED) as zipf: @@ -32,16 +50,30 @@ def extract_zip(archive_path, extract_to, password=None): with zipfile.ZipFile(archive_path, 'r') as zipf: if password: zipf.setpassword(password.encode()) + # Validate all members before extraction + for member in zipf.namelist(): + CompressionService._safe_extract_member(archive_path, member, extract_to) zipf.extractall(extract_to) @staticmethod def extract_tar(archive_path, extract_to): with tarfile.open(archive_path, 'r:*') as tarf: - tarf.extractall(extract_to) + # Validate all members before extraction to prevent path traversal + for member in tarf.getmembers(): + CompressionService._safe_extract_member(archive_path, member.name, extract_to) + # Use data filter for Python 3.12+ or validate manually for earlier versions + try: + tarf.extractall(extract_to, filter='data') + except TypeError: + # Python < 3.12 doesn't support filter parameter, but we already validated + tarf.extractall(extract_to) @staticmethod def extract_7z(archive_path, extract_to, password=None): with py7zr.SevenZipFile(archive_path, 'r', password=password) as szf: + # Validate all members before extraction + for member in szf.getnames(): + CompressionService._safe_extract_member(archive_path, member, extract_to) szf.extractall(extract_to) @staticmethod diff --git a/FileFlow/frontend/js/app.js/auth.js b/FileFlow/frontend/js/app.js/auth.js deleted file mode 100644 index e69de29b..00000000 diff --git a/FileFlow/frontend/js/app.js/file_management.js b/FileFlow/frontend/js/file_management.js similarity index 100% rename from FileFlow/frontend/js/app.js/file_management.js rename to FileFlow/frontend/js/file_management.js diff --git a/FileFlow/frontend/templates/dashboard.html b/FileFlow/frontend/templates/dashboard.html index 4ebfaac7..9bf08aa9 100644 --- a/FileFlow/frontend/templates/dashboard.html +++ b/FileFlow/frontend/templates/dashboard.html @@ -22,7 +22,7 @@
- +
@@ -64,15 +64,11 @@
- - - -