|
124 | 124 | # This will raise ValueError if any required variables are missing |
125 | 125 | validate_required_env_vars() |
126 | 126 |
|
| 127 | +# ===================================================================== |
| 128 | +# SECURITY COMPLIANCE UPDATE: SENTRY ERROR MONITORING |
| 129 | +# ===================================================================== |
| 130 | +import sentry_sdk |
| 131 | +from sentry_sdk.integrations.flask import FlaskIntegration |
| 132 | + |
| 133 | +sentry_dsn = os.getenv('SENTRY_DSN') |
| 134 | +if sentry_dsn: |
| 135 | + def strip_sensitive_data(event, hint): |
| 136 | + # Scrub sensitive data from request data before sending to Sentry |
| 137 | + if 'request' in event: |
| 138 | + request_data = event['request'] |
| 139 | + if 'headers' in request_data: |
| 140 | + for key in ['Authorization', 'Cookie', 'X-CSRF-Token']: |
| 141 | + if key in request_data['headers'] or key.lower() in request_data['headers']: |
| 142 | + request_data['headers'][key] = '[Filtered]' |
| 143 | + request_data['headers'][key.lower()] = '[Filtered]' |
| 144 | + if 'data' in request_data and isinstance(request_data['data'], dict): |
| 145 | + for key in ['password', 'token', 'secret']: |
| 146 | + if key in request_data['data']: |
| 147 | + request_data['data'][key] = '[Filtered]' |
| 148 | + return event |
| 149 | + |
| 150 | + sentry_sdk.init( |
| 151 | + dsn=sentry_dsn, |
| 152 | + integrations=[FlaskIntegration()], |
| 153 | + traces_sample_rate=1.0, |
| 154 | + before_send=strip_sensitive_data, |
| 155 | + environment=env |
| 156 | + ) |
| 157 | + |
127 | 158 | # Apply configuration to Flask app |
128 | 159 | app.config.update(app_config.flask_config) |
129 | 160 |
|
@@ -358,6 +389,15 @@ def handle_unhandled_exception(e): |
358 | 389 | tuple: A Flask JSON response object and an HTTP status code. |
359 | 390 | """ |
360 | 391 |
|
| 392 | + # Capture in Sentry if it's not a standard HTTP exception |
| 393 | + if not isinstance(e, HTTPException): |
| 394 | + try: |
| 395 | + import sentry_sdk |
| 396 | + if os.getenv('SENTRY_DSN'): |
| 397 | + sentry_sdk.capture_exception(e) |
| 398 | + except ImportError: |
| 399 | + pass |
| 400 | + |
361 | 401 | # 1. Handle HTTP Exceptions Normally |
362 | 402 | # If the exception is an intentional HTTP error (e.g., abort(404)), |
363 | 403 | # we should return its intended status code and message, assuming it's |
@@ -517,6 +557,13 @@ def handle_sqlalchemy_exception(e): |
517 | 557 | Dedicated handler for database-related exceptions to prevent SQL injection |
518 | 558 | reconnaissance and schema leakage. |
519 | 559 | """ |
| 560 | + try: |
| 561 | + import sentry_sdk |
| 562 | + if os.getenv('SENTRY_DSN'): |
| 563 | + sentry_sdk.capture_exception(e) |
| 564 | + except ImportError: |
| 565 | + pass |
| 566 | + |
520 | 567 | # 1. Ensure the session is rolled back safely |
521 | 568 | try: |
522 | 569 | db.session.rollback() |
|
0 commit comments