🛡️ CVE-2026-47413 — praisonai-platform

🔴 CVSS 9.6 — Critical ✅ No Known Exploit CWE-269 NVD
9.6
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

praisonai-platform: Any workspace member can add arbitrary user as owner via POST /workspaces/{id}/members

Summary

Type: Privilege escalation / cross-tenant member injection. The POST /workspaces/{workspace_id}/members endpoint is gated only by require_workspace_member(workspace_id) (default min_role="member") and forwards the request body's user_id and role straight into MemberService.add(workspace_id, user_id, role), which has no caller-permission check. A user with the lowest workspace privilege can add any user (including a new attacker-controlled second account, or an existing account they want to grief) as owner of the workspace.

File: src/praisonai-platform/praisonai_platform/api/routes/workspaces.py, lines 92-101; services/member_service.py, lines 26-38.

Root cause: MemberService.add validates only that role is in VALID_ROLES = {"owner", "admin", "member"} — the value, not the caller's right to assign it. The route's Depends(require_workspace_member) resolves to the default min_role="member". So a member-level token plus one POST gives the attacker an alternate identity with owner role inside the same workspace, bypassing every owner-only operation that *would* otherwise gate them.

Affected Code

File 1: src/praisonai-platform/praisonai_platform/api/routes/workspaces.py, lines 92-101.

```python

@router.post("/{workspace_id}/members", response_model=MemberResponse, status_code=status.HTTP_201_CREATED)

async def add_member(

workspace_id: str,

body: MemberAdd,

user: AuthIdentity = Depends(require_workspace_member), # <-- BUG: defaults to min_role="member"

session: AsyncSession = Depends(get_db),

):

member_svc = MemberService(session)

member = await member_svc.add(workspace_id, body.user_id, body.role) # <-- writes any (user, role)

return MemberResponse.model_validate(member)

```

File 2: src/praisonai-platform/praisonai_platform/services/member_service.py, lines 26-38.

```python

async def add(

self,

workspace_id: str,

user_id: str,

role: str = "member",

) -> Member:

"""Add a user to a workspace."""

if role not in VALID_ROLES: # only validates the value

raise ValueError(f"Invalid role: {role}. Must be one of {VALID_ROLES}")

member = Member(workspace_id=workspace_id, user_id=user_id, role=role)

self._session.add(member) # <-- BUG: no caller-permission check

await self._session.flush()

return member

```

Why it's wrong: workspace member management is the textbook capability that must be gated on owner role. The role hierarchy is implemented (MemberService.has_role, member_service.py:80-96), the dependency-tunable min_role parameter exists (require_workspace_member(min_role), deps.py:58), but the POST .../members route uses neither. The VALID_ROLES enum check is purely cosmetic — it accepts "owner" from any caller because the route never asked whether the caller has the right to assign that role.

Exploit Chain

1. Attacker registers two accounts (or recruits a member account on the target workspace W). Account A is an existing member of W; Account B is a fresh signup the attacker controls (any account on the platform — auth/register is open by default). State: attacker holds tokens for both A and B.

2. Attacker authenticates as Account A and POSTs Authorization: Bearer <A_jwt> to POST /workspaces/W/members with body {"user_id": "<B_user_id>", "role": "owner"}. State: control flow enters add_member.

3. require_workspace_member(W, A) passes (A is a member). MemberService.add(W, B, "owner") writes a new row Member(workspace_id=W, user_id=B, role="owner"). State: Account B is now a workspace-W owner.

4. Attacker switches to Account B and acts as workspace owner — change settings, add/remove members, delete the workspace, or pivot to the companion advisories' primitives. State: attacker holds owner of any workspace they had member access to, via a fresh attacker-controlled identity that the original workspace's audit logs cannot easily attribute to A.

5. Final state: with one member-level token plus one POST, the attacker plants an owner-role identity on any workspace they can reach. The same primitive lets the attacker invite a competitor or external-vendor account into the workspace as owner, exfiltrating the workspace's content under that competitor's name.

Security Impact

Severity: sec-critical. CVSS 9.1: network attack, low complexity, low privileges (member tier), no user interaction, scope changed (the new owner is a different security principal), high confidentiality and integrity, no availability claim.

Attacker capability: with one workspace-member token plus one POST request, the attacker grants owner-tier access to any user_id on the platform. From there, full workspace control via the Account B token, plus indirect attribution

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is low, an attacker needs low-level privileges on the target. No user interaction is required. The scope is changed, meaning a successful attack can affect components beyond the vulnerable one. Rated impact: confidentiality high, integrity high, availability none.

Weakness class

CVE-2026-47413 is classified as CWE-269: Improper Privilege Management. Privileges are assigned, dropped or restored incorrectly, leaving an actor with more access than intended.

Affected software

CVE-2026-47413 is recorded against 2 packages.

  • praisonai-platform (fixed in 0.1.4)
  • unknown

Timeline and source

Published on 1 June 2026 and last revised on 1 July 2026. No public exploit is currently recorded for this entry. Record sourced from NVD.

References

github.com (Web)
github.com (Package)

Details

Severity CRITICAL
CVSS Score 9.6
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N
CWE CWE-269
Public Exploit ✅ No
Source NVD
Published 2026-06-01
Updated 2026-08-12
Modified 2026-07-01
Fix URL N/A

Affected Packages

Software From version Fixed in
praisonai-platform 0.1.4
unknown

Similar Threats

Exploit Protection

Are you running praisonai-platform?

CVE-2026-47413 carries CVSS 9.6 Critical rating. BotEraser checks your installation against this and other known CVE records, and blocks IPs associated with exploit activity.

Check My Site For CVE-2026-47413 →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.