diff --git a/app/__init__.py b/app/__init__.py index add218e5d..f7427f9f1 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -286,6 +286,13 @@ def init_app(app): @app.after_request def after_request(response): response.headers.add("X-Content-Type-Options", "nosniff") + + # Some dynamic scan findings + response.headers.add("Cross-Origin-Opener-Policy", "same-origin") + response.headers.add("Cross-Origin-Embedder-Policy", "require-corp") + response.headers.add("Cross-Origin-Resource-Policy", "same-origin") + response.headers.add("Cross-Origin-Opener-Policy", "same-origin") + return response @app.errorhandler(Exception) diff --git a/app/celery/nightly_tasks.py b/app/celery/nightly_tasks.py index f51b0ec9a..01bdbbd67 100644 --- a/app/celery/nightly_tasks.py +++ b/app/celery/nightly_tasks.py @@ -52,7 +52,8 @@ def cleanup_unfinished_jobs(): # The query already checks that the processing_finished time is null, so here we are saying # if it started more than 4 hours ago, that's too long try: - acceptable_finish_time = job.processing_started + timedelta(minutes=5) + if job.processing_started is not None: + acceptable_finish_time = job.processing_started + timedelta(minutes=5) except TypeError: current_app.logger.exception( f"Job ID {job.id} processing_started is {job.processing_started}.", diff --git a/app/service/rest.py b/app/service/rest.py index 657555348..98cb0e963 100644 --- a/app/service/rest.py +++ b/app/service/rest.py @@ -694,7 +694,12 @@ def get_single_month_notification_stats_by_user(service_id, user_id): service_id, start_date, end_date, user_id ) - stats = get_specific_days_stats(results, start_date, end_date=end_date, total_notifications=total_notifications,) + stats = get_specific_days_stats( + results, + start_date, + end_date=end_date, + total_notifications=total_notifications, + ) return jsonify(stats) diff --git a/application.py b/application.py index 25885fc16..0b1256667 100644 --- a/application.py +++ b/application.py @@ -2,9 +2,12 @@ from __future__ import print_function from flask import Flask +from werkzeug.serving import WSGIRequestHandler from app import create_app +WSGIRequestHandler.version_string = lambda self: "SecureServer" + application = Flask("app") create_app(application) diff --git a/notifications_utils/request_helper.py b/notifications_utils/request_helper.py index 48776e69a..d5375065f 100644 --- a/notifications_utils/request_helper.py +++ b/notifications_utils/request_helper.py @@ -76,6 +76,11 @@ class ResponseHeaderMiddleware(object): if SPAN_ID_HEADER.lower() not in lower_existing_header_names: headers.append((SPAN_ID_HEADER, str(req.span_id))) + headers = [ + (key, value) + for key, value in headers + if key.lower() not in ["server", "last-modified"] + ] return start_response(status, headers, exc_info) return self._app(environ, rewrite_response_headers) diff --git a/zap.conf b/zap.conf index f4e88ff07..255e0dde8 100644 --- a/zap.conf +++ b/zap.conf @@ -50,7 +50,7 @@ 10061 WARN (X-AspNet-Version Response Header - Passive/release) 10062 FAIL (PII Disclosure - Passive/beta) 10095 IGNORE (Backup File Disclosure - Active/beta) -10096 WARN (Timestamp Disclosure - Passive/release) +10096 IGNORE (Timestamp Disclosure - Passive/release) 10097 WARN (Hash Disclosure - Passive/beta) 10098 WARN (Cross-Domain Misconfiguration - Passive/release) 10104 WARN (User Agent Fuzzer - Active/beta) @@ -119,3 +119,4 @@ 90030 WARN (WSDL File Detection - Passive/alpha) 90033 WARN (Loosely Scoped Cookie - Passive/release) 90034 WARN (Cloud Metadata Potentially Exposed - Active/beta) +100001 IGNORE (Unexpected Content-Type was returned)