From a1f9cd4114024adf933ce28bf468a38c7991e101 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 31 Jan 2026 18:44:17 +0000 Subject: [PATCH] Fix security concerns - restrictive file permissions and remove secret logging Co-authored-by: Stalin-143 <161853795+Stalin-143@users.noreply.github.com> --- backend/main.py | 4 +++- backend/routes/admin.py | 4 ---- backend/routes/auth.py | 3 +++ 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/backend/main.py b/backend/main.py index a2cfbf3..26b04c9 100644 --- a/backend/main.py +++ b/backend/main.py @@ -123,6 +123,7 @@ def get_dev_fallback_secret(name: str) -> str: Stores the secret in a file to persist across restarts. """ import tempfile + import stat secret_file = os.path.join(tempfile.gettempdir(), f'.openlearnx_dev_{name}') try: if os.path.exists(secret_file): @@ -135,6 +136,8 @@ def get_dev_fallback_secret(name: str) -> str: try: with open(secret_file, 'w') as f: f.write(new_secret) + # Set restrictive permissions (owner read/write only) + os.chmod(secret_file, stat.S_IRUSR | stat.S_IWUSR) except Exception: pass # If we can't persist, just return the generated secret return new_secret @@ -150,7 +153,6 @@ except ValueError as e: _secret_key = os.getenv('SECRET_KEY') or get_dev_fallback_secret('secret_key') _jwt_secret_key = os.getenv('JWT_SECRET_KEY') or get_dev_fallback_secret('jwt_secret_key') _admin_token = os.getenv('ADMIN_TOKEN') or get_dev_fallback_secret('admin_token') - print(f"⚠️ DEV ADMIN_TOKEN (first 8 chars): {_admin_token[:8]}...") app.config.update( SECRET_KEY=_secret_key, diff --git a/backend/routes/admin.py b/backend/routes/admin.py index 6e0d38c..d74505a 100644 --- a/backend/routes/admin.py +++ b/backend/routes/admin.py @@ -29,7 +29,6 @@ def admin_required(f): return jsonify({"error": "Invalid authorization format"}), 401 token = auth_header.split(' ')[1] if len(auth_header.split(' ')) > 1 else None - print(f"Extracted token: '{token}'") # Check environment variable - no fallback for security expected_token = os.getenv('ADMIN_TOKEN') @@ -37,9 +36,6 @@ def admin_required(f): print("❌ ADMIN_TOKEN environment variable not set") return jsonify({"error": "Server configuration error: ADMIN_TOKEN not configured"}), 500 - print(f"Expected token: '{expected_token}'") - print(f"Environment ADMIN_TOKEN: '{os.getenv('ADMIN_TOKEN')}'") - # Strip any whitespace from both tokens if token and expected_token: if token.strip() == expected_token.strip(): diff --git a/backend/routes/auth.py b/backend/routes/auth.py index b2960bb..4d41d65 100644 --- a/backend/routes/auth.py +++ b/backend/routes/auth.py @@ -21,6 +21,7 @@ JWT_SECRET = os.getenv('JWT_SECRET') if not JWT_SECRET: import warnings import tempfile + import stat warnings.warn("JWT_SECRET environment variable not set. Using persistent dev secret.", UserWarning) # Use persistent file-based secret for development to avoid invalidating tokens on restart _secret_file = os.path.join(tempfile.gettempdir(), '.openlearnx_dev_jwt_secret_auth') @@ -33,6 +34,8 @@ if not JWT_SECRET: JWT_SECRET = _secrets.token_hex(32) with open(_secret_file, 'w') as f: f.write(JWT_SECRET) + # Set restrictive permissions (owner read/write only) + os.chmod(_secret_file, stat.S_IRUSR | stat.S_IWUSR) except Exception: import secrets as _secrets JWT_SECRET = _secrets.token_hex(32)