Fix CSRF validation for duplicate cookie values on PATCH
This commit is contained in:
@@ -54,6 +54,28 @@ def _requires_csrf_validation(method: str) -> bool:
|
||||
return method.upper() in CSRF_PROTECTED_METHODS
|
||||
|
||||
|
||||
def _extract_cookie_values(request: Request, cookie_name: str) -> tuple[str, ...]:
|
||||
"""Extracts all values for one cookie name from raw Cookie header order."""
|
||||
|
||||
request_headers = getattr(request, "headers", None)
|
||||
raw_cookie_header = request_headers.get("cookie", "") if request_headers is not None else ""
|
||||
if not raw_cookie_header:
|
||||
return ()
|
||||
|
||||
extracted_values: list[str] = []
|
||||
for cookie_pair in raw_cookie_header.split(";"):
|
||||
normalized_pair = cookie_pair.strip()
|
||||
if not normalized_pair or "=" not in normalized_pair:
|
||||
continue
|
||||
key, value = normalized_pair.split("=", 1)
|
||||
if key.strip() != cookie_name:
|
||||
continue
|
||||
normalized_value = value.strip()
|
||||
if normalized_value:
|
||||
extracted_values.append(normalized_value)
|
||||
return tuple(extracted_values)
|
||||
|
||||
|
||||
def _raise_unauthorized() -> None:
|
||||
"""Raises a 401 challenge response for missing or invalid auth sessions."""
|
||||
|
||||
@@ -94,11 +116,14 @@ def get_request_auth_context(
|
||||
|
||||
if _requires_csrf_validation(request.method) and using_cookie_session:
|
||||
normalized_csrf_header = (csrf_header or "").strip()
|
||||
csrf_candidates = [candidate for candidate in _extract_cookie_values(request, CSRF_COOKIE_NAME) if candidate]
|
||||
normalized_csrf_cookie = (csrf_cookie or "").strip()
|
||||
if normalized_csrf_cookie and normalized_csrf_cookie not in csrf_candidates:
|
||||
csrf_candidates.append(normalized_csrf_cookie)
|
||||
if (
|
||||
not normalized_csrf_cookie
|
||||
not csrf_candidates
|
||||
or not normalized_csrf_header
|
||||
or not hmac.compare_digest(normalized_csrf_cookie, normalized_csrf_header)
|
||||
or not any(hmac.compare_digest(candidate, normalized_csrf_header) for candidate in csrf_candidates)
|
||||
):
|
||||
_raise_csrf_rejected()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user