CVE-2026-47413

CRITICALPre-NVD 9.69.6
EchelonGraph scoreLOW confidence

This critical-severity CVE scores 9.6 under the CNA's CVSS (NVD's own analysis pending). EPSS exploit probability: 0.0%, top 90% of all CVEs by exploit prediction. GitHub Security Advisory data not yet ingested — confidence will rise once GHSA publishes (typical lag: hours to days for open-source ecosystem CVEs; never for infrastructure-only CVEs).

Triggered by: NVD CVSS baseline
Sources: cna:github_m, epss
9.6
EchelonGraph verdictPlan a fixSerious severity, but no confirmed exploitation yet.
  • High severity, but no confirmed exploitation yet
CISA-KEV: Not listedEPSS: 0%CVSS: 9.6Exploit: NoneExposed: 0

No vendor fix yet — apply a workaround or compensating control (WAF / firewall / segmentation) and watch for a patch.

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.

@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.

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

  • 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.
  • Attacker authenticates as Account A and POSTs Authorization: Bearer to POST /workspaces/W/members with body {"user_id": "", "role": "owner"}. State: control flow enters add_member.
  • 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.
  • 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.
  • 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: the original workspace's audit logs see "user A added user B as owner" but the audit trail cannot tell that B is attacker-controlled. Preconditions: praisonai-platform is deployed multi-tenant; the attacker has any membership token in the target workspace; the attacker can register or knows any other user_id on the platform. Differential: source-inspection-verified. The asymmetry between MemberService.has_role (clearly tiered) and add_member's default min_role="member" confirms the gap. With the suggested fix below, the gate refuses the member-tier token, the elevated POST returns 403, and the second-identity owner is never created.

Suggested Fix

--- a/src/praisonai-platform/praisonai_platform/api/routes/workspaces.py
+++ b/src/praisonai-platform/praisonai_platform/api/routes/workspaces.py
@@ -90,11 +90,15 @@
+def _require_workspace_owner(workspace_id: str, user, session):
+    return require_workspace_member(workspace_id, user, session, min_role="owner")
+
 @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),
+ user: AuthIdentity = Depends(_require_workspace_owner), session: AsyncSession = Depends(get_db), ): member_svc = MemberService(session) + if body.role == "owner" and not await member_svc.has_role(workspace_id, user.id, "owner"): + raise HTTPException(status_code=403, detail="Only owners can add other owners") member = await member_svc.add(workspace_id, body.user_id, body.role)

The four other workspace mutation endpoints (update_workspace, delete_workspace, update_member_role, remove_member) exhibit the same default-min-role gap and are filed as their own advisories.

CVSS v3
9.6
EG Score
9.6(low)
EPSS
9.5%
KEV
Not listed

Published

June 1, 2026

Last Modified

June 1, 2026

Vendor Advisories for CVE-2026-47413(1)

These vendors published their own advisory mentioning this CVE — often with vendor-specific remediation steps + affected product lists not in NVD.

Affected Packages

(1 across 1 ecosystem)
PyPI(1)
PackageVulnerable rangeFixed inDependents
praisonai-platform0.1.0, 0.1.1, 0.1.2, 0.1.30.1.4

Data Freshness Timeline

(refreshed 10× in last 7d / 102× in last 30d)

Each row is a source pipeline that fetched or updated this CVE on that date, with what changed. For example, "NVD update" means NVD published or revised its analysis for this CVE; "MITRE cvelistV5" means we ingested or refreshed it from the CNA feed. Most recent first.

Showing the most recent 100 of 136 total refreshes for this CVE.

  1. 2026-07-02 23:00 UTCEG score recompute
  2. 2026-07-02 18:35 UTCEG score recompute
  3. 2026-07-02 12:48 UTCEG score recompute
  4. 2026-07-02 07:54 UTCEG score recompute
  5. 2026-07-02 02:19 UTCEG score recompute
  6. 2026-07-01 21:08 UTCEG score recompute
  7. 2026-07-01 16:47 UTCEG score recompute
  8. 2026-07-01 12:32 UTCEG score recompute
  9. 2026-07-01 08:19 UTCEG score recompute
  10. 2026-07-01 00:32 UTCEG score recompute
  11. 2026-06-30 05:27 UTCEG score recompute
  12. 2026-06-30 00:36 UTCEG score recompute
  13. 2026-06-29 20:22 UTCEG score recompute
  14. 2026-06-29 16:09 UTCEG score recompute
  15. 2026-06-29 11:50 UTCEG score recompute
  16. 2026-06-29 00:14 UTCEG score recompute
  17. 2026-06-28 19:51 UTCEG score recompute
  18. 2026-06-28 15:36 UTCEG score recompute
  19. 2026-06-28 11:13 UTCEG score recompute
  20. 2026-06-28 07:00 UTCEG score recompute
  21. 2026-06-28 02:46 UTCEG score recompute
  22. 2026-06-27 22:33 UTCEG score recompute
  23. 2026-06-27 18:20 UTCEG score recompute
  24. 2026-06-27 14:07 UTCEG score recompute
  25. 2026-06-27 09:48 UTCEG score recompute
Show 75 more
  1. 2026-06-27 05:34 UTCEG score recompute
  2. 2026-06-27 01:21 UTCEG score recompute
  3. 2026-06-26 20:11 UTCEG score recompute
  4. 2026-06-26 15:58 UTCEG score recompute
  5. 2026-06-26 01:45 UTCEG score recompute
  6. 2026-06-25 19:49 UTCEG score recompute
  7. 2026-06-25 15:36 UTCEG score recompute
  8. 2026-06-25 11:22 UTCEG score recompute
  9. 2026-06-25 07:09 UTCEG score recompute
  10. 2026-06-25 02:45 UTCEG score recompute
  11. 2026-06-24 22:31 UTCEG score recompute
  12. 2026-06-24 15:00 UTCEG score recompute
  13. 2026-06-24 02:07 UTCEG score recompute
  14. 2026-06-18 22:02 UTCEG score recompute
  15. 2026-06-18 09:57 UTCEG score recompute
  16. 2026-06-18 02:00 UTCEG score recompute
  17. 2026-06-17 21:47 UTCEG score recompute
  18. 2026-06-17 17:34 UTCEG score recompute
  19. 2026-06-17 12:04 UTCEG score recompute
  20. 2026-06-17 07:49 UTCEG score recompute
  21. 2026-06-17 03:36 UTCEG score recompute
  22. 2026-06-16 23:23 UTCEG score recompute
  23. 2026-06-16 19:11 UTCEG score recompute
  24. 2026-06-16 14:57 UTCEG score recompute
  25. 2026-06-16 09:49 UTCEG score recompute
  26. 2026-06-16 05:36 UTCEG score recompute
  27. 2026-06-16 01:22 UTCEG score recompute
  28. 2026-06-15 21:08 UTCEG score recompute
  29. 2026-06-15 16:21 UTCEG score recompute
  30. 2026-06-15 12:08 UTCEG score recompute
  31. 2026-06-15 06:55 UTCEG score recompute
  32. 2026-06-15 02:41 UTCEG score recompute
  33. 2026-06-14 23:18 UTCEPSS rescore
  34. 2026-06-14 22:28 UTCEG score recompute
  35. 2026-06-14 18:14 UTCEG score recompute
  36. 2026-06-14 13:41 UTCEG score recompute
  37. 2026-06-14 09:27 UTCEG score recompute
  38. 2026-06-14 05:14 UTCEG score recompute
  39. 2026-06-14 00:55 UTCEG score recompute
  40. 2026-06-13 23:00 UTCEPSS rescore
  41. 2026-06-13 20:42 UTCEG score recompute
  42. 2026-06-13 16:29 UTCEG score recompute
  43. 2026-06-13 12:16 UTCEG score recompute
  44. 2026-06-13 08:00 UTCEG score recompute
  45. 2026-06-13 03:47 UTCEG score recompute
  46. 2026-06-12 23:34 UTCEG score recompute
  47. 2026-06-12 23:12 UTCEPSS rescore
  48. 2026-06-12 19:21 UTCEG score recompute
  49. 2026-06-12 15:06 UTCEG score recompute
  50. 2026-06-12 10:53 UTCEG score recompute
  51. 2026-06-12 06:41 UTCEG score recompute
  52. 2026-06-12 02:28 UTCEG score recompute
  53. 2026-06-11 22:15 UTCEG score recompute
  54. 2026-06-11 18:02 UTCEG score recompute
  55. 2026-06-11 13:47 UTCEG score recompute
  56. 2026-06-11 09:34 UTCEG score recompute
  57. 2026-06-11 05:21 UTCEG score recompute
  58. 2026-06-11 01:08 UTCEG score recompute
  59. 2026-06-10 20:55 UTCEG score recompute
  60. 2026-06-10 16:42 UTCEG score recompute
  61. 2026-06-10 12:28 UTCEG score recompute
  62. 2026-06-10 08:15 UTCEG score recompute
  63. 2026-06-10 04:02 UTCEG score recompute
  64. 2026-06-09 23:49 UTCEG score recompute
  65. 2026-06-09 19:36 UTCEG score recompute
  66. 2026-06-09 15:23 UTCEG score recompute
  67. 2026-06-09 11:10 UTCEG score recompute
  68. 2026-06-09 06:57 UTCEG score recompute
  69. 2026-06-09 02:44 UTCEG score recompute
  70. 2026-06-08 22:31 UTCEG score recompute
  71. 2026-06-08 18:17 UTCEG score recompute
  72. 2026-06-08 11:27 UTCEG score recompute
  73. 2026-06-08 07:14 UTCEG score recompute
  74. 2026-06-08 03:01 UTCEG score recompute
  75. 2026-06-07 22:48 UTCEG score recompute

Frequently asked(5)

What is CVE-2026-47413?
CVE-2026-47413 is a critical vulnerability published on June 1, 2026. 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/{workspaceid}/members endpoint is gated only by requireworkspacemember(workspaceid) (default…
When was CVE-2026-47413 disclosed?
CVE-2026-47413 was first published in the National Vulnerability Database on June 1, 2026. EchelonGraph re-ingests CVE updates from NVD on a 2-hour cycle, so this page reflects the latest published state.
Is CVE-2026-47413 actively exploited?
CVE-2026-47413 is not currently on CISA's Known Exploited Vulnerabilities catalog. FIRST EPSS estimates a 9.5% percentile likelihood of exploitation in the next 30 days — higher percentiles indicate greater predicted risk.
What is the CVSS score of CVE-2026-47413?
CVE-2026-47413 has a CVSS v4.0 base score of 9.6 (CNA self-assessment; NVD's own analysis pending). The EG score is currently aggregating — additional source signals are being incorporated as they become available..
How do I remediate CVE-2026-47413?
Patch to the fixed version published by the affected vendor. Where vendor advisories exist for CVE-2026-47413, EchelonGraph cross-links them in the Vendor Advisories panel below — those typically contain the canonical remediation steps, fixed version numbers, and any vendor-specific mitigations.

Dependency Blast Radius

See which npm, PyPI, Go, and Maven packages are affected by CVE-2026-47413

Explore →

Is Your Infrastructure Affected by CVE-2026-47413?

EchelonGraph automatically scans your cloud infrastructure and maps CVE exposure using blast radius analysis.