Fix CSRF validation for duplicate cookie values on PATCH

This commit is contained in:
2026-03-02 18:09:27 -03:00
parent 2a5dfc3713
commit 1a04b23e89
3 changed files with 86 additions and 2 deletions

View File

@@ -364,6 +364,7 @@ if "app.services.routing_pipeline" not in sys.modules:
from fastapi import HTTPException
from app.api.auth import AuthContext, require_admin
from app.api import auth as auth_dependency_module
from app.api import routes_auth as auth_routes_module
from app.api import routes_documents as documents_routes_module
from app.core import config as config_module
@@ -420,6 +421,63 @@ class AuthDependencyTests(unittest.TestCase):
resolved = require_admin(context=auth_context)
self.assertEqual(resolved.role, UserRole.ADMIN)
def test_csrf_validation_accepts_matching_token_among_duplicate_cookie_values(self) -> None:
"""PATCH CSRF validation accepts header token matching any duplicate csrf cookie value."""
request = SimpleNamespace(
method="PATCH",
headers={"cookie": "dcm_session=session-token; dcm_csrf=stale-token; dcm_csrf=fresh-token"},
)
resolved_session = SimpleNamespace(
id=uuid.uuid4(),
expires_at=datetime.now(UTC),
user=SimpleNamespace(
id=uuid.uuid4(),
username="admin",
role=UserRole.ADMIN,
),
)
with patch.object(auth_dependency_module, "resolve_auth_session", return_value=resolved_session):
context = auth_dependency_module.get_request_auth_context(
request=request,
credentials=None,
csrf_header="fresh-token",
csrf_cookie="stale-token",
session_cookie="session-token",
session=SimpleNamespace(),
)
self.assertEqual(context.username, "admin")
self.assertEqual(context.role, UserRole.ADMIN)
def test_csrf_validation_rejects_when_header_does_not_match_any_cookie_value(self) -> None:
"""PATCH CSRF validation rejects requests when header token matches no csrf cookie values."""
request = SimpleNamespace(
method="PATCH",
headers={"cookie": "dcm_session=session-token; dcm_csrf=stale-token; dcm_csrf=fresh-token"},
)
resolved_session = SimpleNamespace(
id=uuid.uuid4(),
expires_at=datetime.now(UTC),
user=SimpleNamespace(
id=uuid.uuid4(),
username="admin",
role=UserRole.ADMIN,
),
)
with patch.object(auth_dependency_module, "resolve_auth_session", return_value=resolved_session):
with self.assertRaises(HTTPException) as raised:
auth_dependency_module.get_request_auth_context(
request=request,
credentials=None,
csrf_header="unknown-token",
csrf_cookie="stale-token",
session_cookie="session-token",
session=SimpleNamespace(),
)
self.assertEqual(raised.exception.status_code, 403)
self.assertEqual(raised.exception.detail, "Invalid CSRF token")
class DocumentCatalogVisibilityTests(unittest.TestCase):
"""Verifies predefined tag and path discovery visibility by caller role."""