mirror of
https://github.com/makeplane/plane.git
synced 2026-07-09 12:00:38 +02:00
[WEB-7787] fix(security): block deactivated user login and fix WorkspaceOwnerPermission (#9290)
GHSA-rmmf-rj2q-3rrg: save_user_data() was unconditionally setting is_active=True on every login, silently reactivating any admin-deactivated account. Fix: add an early guard in complete_login_or_signup() that raises USER_ACCOUNT_DEACTIVATED (5019) before any session or save logic if the existing user's is_active=False. Remove the is_active=True assignment and the associated user_activation_email call from save_user_data(). Also remove the now-unused user_activation_email and base_host imports. GHSA-wjgv-cq7w-258v: WorkspaceOwnerPermission in both app/permissions/ and utils/permissions/ was filtering WorkspaceMember without is_active=True, allowing a deactivated workspace owner/admin to retain API access. Add is_active=True to both copies to match every other permission class. Co-authored-by: Plane AI <noreply@plane.so>
This commit is contained in:
@@ -54,7 +54,7 @@ class WorkspaceOwnerPermission(BasePermission):
|
||||
return False
|
||||
|
||||
return WorkspaceMember.objects.filter(
|
||||
workspace__slug=view.workspace_slug, member=request.user, role=Admin
|
||||
workspace__slug=view.workspace_slug, member=request.user, role=Admin, is_active=True
|
||||
).exists()
|
||||
|
||||
|
||||
|
||||
@@ -19,14 +19,11 @@ from django.utils import timezone
|
||||
# Third party imports
|
||||
from zxcvbn import zxcvbn
|
||||
|
||||
from plane.bgtasks.user_activation_email_task import user_activation_email
|
||||
|
||||
# Module imports
|
||||
from plane.db.models import FileAsset, Profile, User, WorkspaceMemberInvite
|
||||
from plane.license.utils.instance_value import get_configuration_value
|
||||
from plane.settings.storage import S3Storage
|
||||
from plane.utils.exception_logger import log_exception
|
||||
from plane.utils.host import base_host
|
||||
from plane.utils.ip_address import get_client_ip
|
||||
|
||||
from .error import AUTHENTICATION_ERROR_CODES, AuthenticationException
|
||||
@@ -239,11 +236,6 @@ class Adapter:
|
||||
user.last_login_ip = get_client_ip(request=self.request)
|
||||
user.last_login_uagent = self.request.META.get("HTTP_USER_AGENT")
|
||||
user.token_updated_at = timezone.now()
|
||||
# If user is not active, send the activation email and set the user as active
|
||||
if not user.is_active:
|
||||
user_activation_email.delay(base_host(request=self.request), user.id)
|
||||
# Set user as active
|
||||
user.is_active = True
|
||||
user.save()
|
||||
return user
|
||||
|
||||
@@ -309,6 +301,16 @@ class Adapter:
|
||||
|
||||
# Check if the user is present
|
||||
user = User.objects.filter(email=email).first()
|
||||
|
||||
# Reject deactivated accounts before any session or save logic.
|
||||
# Without this check, save_user_data() would reactivate the account (GHSA-rmmf-rj2q-3rrg).
|
||||
if user and not user.is_active:
|
||||
raise AuthenticationException(
|
||||
error_code=AUTHENTICATION_ERROR_CODES["USER_ACCOUNT_DEACTIVATED"],
|
||||
error_message="USER_ACCOUNT_DEACTIVATED",
|
||||
payload={"email": email},
|
||||
)
|
||||
|
||||
# Check if sign up case or login
|
||||
is_signup = bool(user)
|
||||
# If user is not present, create a new user
|
||||
|
||||
@@ -54,7 +54,7 @@ class WorkspaceOwnerPermission(BasePermission):
|
||||
return False
|
||||
|
||||
return WorkspaceMember.objects.filter(
|
||||
workspace__slug=view.workspace_slug, member=request.user, role=Admin
|
||||
workspace__slug=view.workspace_slug, member=request.user, role=Admin, is_active=True
|
||||
).exists()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user