From 641ef9ca70e48c5ebcbfc2e0bc96e3c41dd092b2 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 22:43:13 +0000 Subject: [PATCH] Fix information disclosure vulnerability in auth decorator Remove exception string details (`str(e)`) from `login_required` error response in `auth/utils.py` to prevent leaking internal error or system details to unauthenticated callers. Add test suite in `tests/test_auth_utils.py` verifying error messages do not disclose internal exception details. Co-authored-by: Pmaster-dev <293764797+Pmaster-dev@users.noreply.github.com> --- auth/utils.py | 4 +-- tests/test_auth_utils.py | 58 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 tests/test_auth_utils.py diff --git a/auth/utils.py b/auth/utils.py index 4bded89..a060433 100644 --- a/auth/utils.py +++ b/auth/utils.py @@ -128,8 +128,8 @@ def decorated_function(*args, **kwargs): g.user_id = user_id g.user = user_data return f(*args, **kwargs) - except Exception as e: - return jsonify({'error': 'Unauthorized', 'details': str(e)}), 401 + except Exception: + return jsonify({'error': 'Unauthorized'}), 401 return decorated_function diff --git a/tests/test_auth_utils.py b/tests/test_auth_utils.py new file mode 100644 index 0000000..64bfd98 --- /dev/null +++ b/tests/test_auth_utils.py @@ -0,0 +1,58 @@ +import sys +from unittest.mock import MagicMock + +# Mock cache_db module before importing auth.utils +mock_cache_db = MagicMock() +mock_redis = MagicMock() +mock_user = MagicMock() +mock_cache_db.redis_client.redis_client = mock_redis +mock_cache_db.models.User = mock_user +sys.modules['cache_db'] = mock_cache_db +sys.modules['cache_db.redis_client'] = mock_cache_db.redis_client +sys.modules['cache_db.models'] = mock_cache_db.models + +import pytest +from flask import Flask, jsonify +from unittest.mock import patch +from auth.utils import login_required, PasswordUtils, JWTUtils + + +@pytest.fixture +def app(): + app = Flask(__name__) + app.config['SECRET_KEY'] = 'test-secret' + + @app.route('/protected') + @login_required + def protected(): + return jsonify({'message': 'success'}) + + return app + + +def test_login_required_unauthorized_does_not_leak_details(app): + with app.test_request_context('/protected'): + with patch('auth.utils.verify_jwt_in_request', side_effect=RuntimeError("Sensitive DB internal error details")): + client = app.test_client() + response = client.get('/protected') + + assert response.status_code == 401 + json_data = response.get_json() + assert json_data == {'error': 'Unauthorized'} + assert 'details' not in json_data + assert 'Sensitive DB internal error details' not in str(json_data) + + +def test_password_utils(): + hashed = PasswordUtils.hash_password("securepassword123") + assert PasswordUtils.verify_password("securepassword123", hashed) + assert not PasswordUtils.verify_password("wrongpassword", hashed) + + +def test_jwt_utils(): + access, refresh = JWTUtils.create_tokens("123", "testuser") + assert access is not None + assert refresh is not None + payload = JWTUtils.decode_token(access) + assert payload['user_id'] == "123" + assert payload['username'] == "testuser"