Overview

The praisonai-platform is vulnerable to a vertical privilege escalation attack. The PATCH /workspaces/{workspace_id}/members/{user_id} endpoint is gated by require_workspace_member(workspace_id), which defaults to min_role="member" and is never overridden by the route. This allows any member of a workspace to escalate their privileges to owner or promote other members to owner without proper authorization checks.

Technical Details

The vulnerability is caused by the improper implementation of role checks in the update_member_role function in src/praisonai-platform/praisonai_platform/api/routes/workspaces.py. The require_workspace_member dependency defaults to min_role="member", which is the lowest privilege tier. The handler then calls MemberService.update_role(workspace_id, user_id, body.role), which sets the target member's role to whatever the request body specifies without checking if the caller has owner-or-admin privilege or if the new role is higher than the caller's own role.

Affected Code

The affected code includes: - src/praisonai-platform/praisonai_platform/api/routes/workspaces.py, lines 115-127 - src/praisonai-platform/praisonai_platform/services/member_service.py, lines 55-69 - src/praisonai-platform/praisonai_platform/api/deps.py, lines 54-73

Impact Analysis

The impact of this vulnerability is severe. An attacker with a member-level account in a workspace can escalate their privileges to owner in a single HTTP request. This allows them to gain full administrative control of the workspace, including the ability to add/remove members, change settings, delete the workspace, and exfiltrate sensitive data.

Mitigation

To mitigate this vulnerability, two changes are suggested: 1. The route must resolve require_workspace_member with min_role="owner" (or at least "admin"). 2. MemberService.update_role should refuse to set a target's role higher than the caller's own role.

Suggested Fix

The suggested fix involves modifying the update_member_role function to use a custom dependency that requires the caller to have the owner role. Additionally, the MemberService.update_role method should be updated to check if the caller has the owner role before updating the target member's role. ```python def _require_owner(workspace_id: str, user, session): return require_workspace_member(workspace_id, user, session, min_role="owner") @router.patch("/{workspace_id}/members/{user_id}", response_model=MemberResponse) async def update_member_role( workspace_id: str, user_id: str, body: MemberUpdate, user: AuthIdentity = Depends(_require_owner), session: AsyncSession = Depends(get_db), ): member_svc = MemberService(session) if not await member_svc.has_role(workspace_id, user.id, "owner"): raise HTTPException(status_code=403, detail="Only owners can change member roles") member = await member_svc.update_role(workspace_id, user_id, body.role) ```

Conclusion

In conclusion, the praisonai-platform is vulnerable to a critical vertical privilege escalation attack. The vulnerability can be mitigated by implementing proper role checks and modifying the require_workspace_member dependency to require the owner role. The suggested fix provides a solution to prevent this vulnerability from being exploited.