1
0
mirror of https://github.com/quay/quay.git synced 2026-01-26 06:21:37 +03:00
Files
quay/util/http.py
Ivan Bazulic ac12b5243e security: Add Vary header to 404 responses (PROJQUAY-7304) (#2938)
Add `Vary: Origin` header to the 404 responses to instruct browsers (and other utilities) to cache various requests properly (based on their origin) in order to avoid cache poisoning. See the [W3C security details](https://www.w3.org/TR/2020/SPSD-cors-20200602/#resource-security) for more information.
2024-06-11 14:21:00 -04:00

75 lines
2.2 KiB
Python

import json
import logging
from flask import current_app, make_response, request
from werkzeug.exceptions import HTTPException
from app import analytics
from auth.auth_context import get_authenticated_context
logger = logging.getLogger(__name__)
DEFAULT_MESSAGE = {}
DEFAULT_MESSAGE[400] = "Invalid Request"
DEFAULT_MESSAGE[401] = "Unauthorized"
DEFAULT_MESSAGE[403] = "Permission Denied"
DEFAULT_MESSAGE[404] = "Not Found"
DEFAULT_MESSAGE[409] = "Conflict"
DEFAULT_MESSAGE[501] = "Not Implemented"
def _abort(status_code, data_object, description, headers):
# Add CORS headers to all errors
options_resp = current_app.make_default_options_response()
headers["Access-Control-Allow-Origin"] = "*"
headers["Access-Control-Allow-Methods"] = options_resp.headers["allow"]
headers["Access-Control-Max-Age"] = str(21600)
headers["Access-Control-Allow-Headers"] = ["Authorization", "Content-Type"]
headers["Vary"] = "Origin"
resp = make_response(json.dumps(data_object), status_code, headers)
# Report the abort to the user.
# Raising HTTPException as workaround for https://github.com/pallets/werkzeug/issues/1098
new_exception = HTTPException(response=resp, description=description)
new_exception.code = status_code
raise new_exception
def exact_abort(status_code, message=None):
data = {}
if message is not None:
data["error"] = message
_abort(status_code, data, message or None, {})
def abort(status_code, message=None, issue=None, headers=None, **kwargs):
message = str(message) % kwargs if message else DEFAULT_MESSAGE.get(status_code, "")
params = dict(request.view_args or {})
params.update(kwargs)
params["url"] = request.url
params["status_code"] = status_code
params["message"] = message
# Add the user information.
auth_context = get_authenticated_context()
if auth_context is not None:
message = "%s (authorized: %s)" % (message, auth_context.description)
# Log the abort.
logger.error("Error %s: %s; Arguments: %s" % (status_code, message, params))
# Create the final response data and message.
data = {}
data["error"] = message
if headers is None:
headers = {}
_abort(status_code, data, message, headers)