From c03149c2758251aa1cd266084b45be1e155ef9dd Mon Sep 17 00:00:00 2001 From: Manish Gupta Date: Wed, 24 Jun 2026 18:05:14 +0530 Subject: [PATCH] fix(security): address CR review on project invite token validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use request.user directly instead of re-querying User by exact project_invite.email — avoids case-variant miss after the case-insensitive email check already validated the authenticated user (CR comment 1) - Validate `accepted` as a real boolean before saving — form-encoded strings like "false" are truthy and could accidentally create memberships (CR comment 2) Co-authored-by: Plane AI --- apps/api/plane/app/views/project/invite.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/api/plane/app/views/project/invite.py b/apps/api/plane/app/views/project/invite.py index 3aa510ec0f..33673a1acc 100644 --- a/apps/api/plane/app/views/project/invite.py +++ b/apps/api/plane/app/views/project/invite.py @@ -211,13 +211,20 @@ class ProjectJoinEndpoint(BaseAPIView): ) if project_invite.responded_at is None: - project_invite.accepted = request.data.get("accepted", False) + accepted = request.data.get("accepted", False) + if not isinstance(accepted, bool): + return Response( + {"error": "`accepted` must be a boolean"}, + status=status.HTTP_400_BAD_REQUEST, + ) + project_invite.accepted = accepted project_invite.responded_at = timezone.now() project_invite.save() if project_invite.accepted: - # Check if the user account exists - user = User.objects.filter(email=project_invite.email).first() + # Use the authenticated user directly — they've already been + # validated as the invite recipient above. + user = request.user # Check if user is a part of workspace workspace_member = WorkspaceMember.objects.filter(workspace__slug=slug, member=user).first()