CWE-862
Allowed-with-ReviewMissing Authorization
Abstraction: Class · Status: Incomplete
The product does not perform an authorization check when an actor attempts to access a resource or perform an action.
15228 vulnerabilities reference this CWE, most recent first.
GHSA-C28G-VH7M-FM7V
Vulnerability from github – Published: 2026-04-29 21:27 – Updated: 2026-05-19 15:56Impact
OpenClaw deployments before 2026.4.21 could treat a non-owner sender as authorized for owner-enforced slash commands when all of the following were true:
- a channel plugin declared
commands.enforceOwnerForCommands: true; - the channel accepted wildcard inbound senders with
allowFrom: ["*"]; - no explicit
commands.ownerAllowFromwas configured.
In that state, src/auto-reply/command-auth.ts reused the channel inbound wildcard as part of the command-owner decision. A sender who was not the owner could therefore pass the owner-command gate for commands such as /send, /config, or /debug on the affected channel.
The issue is limited to the command-owner authorization axis. It does not by itself grant owner-only tool access, host/sandbox access, or gateway administrator scope.
Affected Packages / Versions
- Package:
openclawon npm - Affected versions:
<= 2026.4.20 - Patched version:
2026.4.21
The latest public release, 2026.4.21, contains the fix.
Patches
The fix requires a concrete owner identity or internal operator-admin scope when a plugin enforces owner-only commands. Wildcard channel allowFrom no longer implies wildcard command ownership.
Fix commits:
2aa93d44a1b2c7058c371f261fda2b5d4de4a882onmain995febb7b1e811ff6a1df5b18c22de94103f4c9fin the2026.4.21release line
Workarounds
Upgrade to openclaw@2026.4.21 or later. Before upgrading, avoid wildcard/open-DM sender policy on owner-enforced channels, or configure commands.ownerAllowFrom to the intended owner identities.
Credits
OpenClaw thanks @zsxsoft for reporting.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 2026.4.20"
},
"package": {
"ecosystem": "npm",
"name": "openclaw"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2026.4.21"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-44991"
],
"database_specific": {
"cwe_ids": [
"CWE-862"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-29T21:27:05Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "## Impact\n\nOpenClaw deployments before `2026.4.21` could treat a non-owner sender as authorized for owner-enforced slash commands when all of the following were true:\n\n- a channel plugin declared `commands.enforceOwnerForCommands: true`;\n- the channel accepted wildcard inbound senders with `allowFrom: [\"*\"]`;\n- no explicit `commands.ownerAllowFrom` was configured.\n\nIn that state, `src/auto-reply/command-auth.ts` reused the channel inbound wildcard as part of the command-owner decision. A sender who was not the owner could therefore pass the owner-command gate for commands such as `/send`, `/config`, or `/debug` on the affected channel.\n\nThe issue is limited to the command-owner authorization axis. It does not by itself grant owner-only tool access, host/sandbox access, or gateway administrator scope.\n\n## Affected Packages / Versions\n\n- Package: `openclaw` on npm\n- Affected versions: `\u003c= 2026.4.20`\n- Patched version: `2026.4.21`\n\nThe latest public release, `2026.4.21`, contains the fix.\n\n## Patches\n\nThe fix requires a concrete owner identity or internal operator-admin scope when a plugin enforces owner-only commands. Wildcard channel `allowFrom` no longer implies wildcard command ownership.\n\nFix commits:\n\n- `2aa93d44a1b2c7058c371f261fda2b5d4de4a882` on `main`\n- `995febb7b1e811ff6a1df5b18c22de94103f4c9f` in the `2026.4.21` release line\n\n## Workarounds\n\nUpgrade to `openclaw@2026.4.21` or later. Before upgrading, avoid wildcard/open-DM sender policy on owner-enforced channels, or configure `commands.ownerAllowFrom` to the intended owner identities.\n\n## Credits\n\nOpenClaw thanks @zsxsoft for reporting.",
"id": "GHSA-c28g-vh7m-fm7v",
"modified": "2026-05-19T15:56:06Z",
"published": "2026-04-29T21:27:05Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-c28g-vh7m-fm7v"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-44991"
},
{
"type": "WEB",
"url": "https://github.com/openclaw/openclaw/commit/2aa93d44a1b2c7058c371f261fda2b5d4de4a882"
},
{
"type": "WEB",
"url": "https://github.com/openclaw/openclaw/commit/995febb7b1e811ff6a1df5b18c22de94103f4c9f"
},
{
"type": "PACKAGE",
"url": "https://github.com/openclaw/openclaw"
},
{
"type": "WEB",
"url": "https://www.vulncheck.com/advisories/openclaw-authorization-bypass-in-owner-enforced-commands-via-wildcard-channel-senders"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "OpenClaw: Owner-enforced commands could accept wildcard channel senders as command owners"
}
GHSA-C28Q-M4GF-VG4Q
Vulnerability from github – Published: 2026-06-12 18:31 – Updated: 2026-06-12 18:31Mattermost versions 11.6.x <= 11.6.1, 11.5.x <= 11.5.4, 10.11.x <= 10.11.15, 10.11.x <= 10.11.16 Fail to enforce PermissionInviteUser when setting AllowOpenInvite or AllowedDomains during team creation (the check was only applied on update/patch), which allows an authenticated user holding PermissionCreateTeam but not PermissionInviteUser on the resulting team to configure invite-controlled team settings (make the team publicly joinable via open invite and/or constrain membership via allowed domains) that they are not permitted to set on an existing team via POST /api/v4/teams with allow_open_invite: true and/or a non-empty allowed_domains in the request body.. Mattermost Advisory ID: MMSA-2026-00655
{
"affected": [],
"aliases": [
"CVE-2026-6689"
],
"database_specific": {
"cwe_ids": [
"CWE-862"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-06-12T17:16:27Z",
"severity": "MODERATE"
},
"details": "Mattermost versions 11.6.x \u003c= 11.6.1, 11.5.x \u003c= 11.5.4, 10.11.x \u003c= 10.11.15, 10.11.x \u003c= 10.11.16 Fail to enforce PermissionInviteUser when setting AllowOpenInvite or AllowedDomains during team creation (the check was only applied on update/patch), which allows an authenticated user holding PermissionCreateTeam but not PermissionInviteUser on the resulting team to configure invite-controlled team settings (make the team publicly joinable via open invite and/or constrain membership via allowed domains) that they are not permitted to set on an existing team via POST /api/v4/teams with allow_open_invite: true and/or a non-empty allowed_domains in the request body.. Mattermost Advisory ID: MMSA-2026-00655",
"id": "GHSA-c28q-m4gf-vg4q",
"modified": "2026-06-12T18:31:59Z",
"published": "2026-06-12T18:31:59Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-6689"
},
{
"type": "WEB",
"url": "https://mattermost.com/security-updates"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-C2F4-R954-QP5R
Vulnerability from github – Published: 2025-12-04 15:30 – Updated: 2025-12-04 15:30A vulnerability in Synology Mail Server allows remote authenticated attackers to read and write non-sensitive settings, and disable some non-critical functions.
{
"affected": [],
"aliases": [
"CVE-2025-2848"
],
"database_specific": {
"cwe_ids": [
"CWE-862"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-12-04T15:15:57Z",
"severity": "MODERATE"
},
"details": "A vulnerability in Synology Mail Server allows remote authenticated attackers to read and write non-sensitive settings, and disable some non-critical functions.",
"id": "GHSA-c2f4-r954-qp5r",
"modified": "2025-12-04T15:30:33Z",
"published": "2025-12-04T15:30:33Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-2848"
},
{
"type": "WEB",
"url": "https://www.synology.com/en-global/security/advisory/Synology_SA_25_05"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L",
"type": "CVSS_V3"
}
]
}
GHSA-C2FP-7MJG-8PF9
Vulnerability from github – Published: 2024-01-11 09:30 – Updated: 2024-01-11 09:30The Export WP Page to Static HTML/CSS plugin for WordPress is vulnerable to unauthorized access of data and modification of data due to a missing capability check on multiple AJAX actions in all versions up to, and including, 2.1.9. This makes it possible for authenticated attackers, with subscriber-level access and above, to disclose sensitive information or perform unauthorized actions, such as saving advanced plugin settings.
{
"affected": [],
"aliases": [
"CVE-2023-6369"
],
"database_specific": {
"cwe_ids": [
"CWE-862"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-01-11T09:15:48Z",
"severity": "MODERATE"
},
"details": "The Export WP Page to Static HTML/CSS plugin for WordPress is vulnerable to unauthorized access of data and modification of data due to a missing capability check on multiple AJAX actions in all versions up to, and including, 2.1.9. This makes it possible for authenticated attackers, with subscriber-level access and above, to disclose sensitive information or perform unauthorized actions, such as saving advanced plugin settings.",
"id": "GHSA-c2fp-7mjg-8pf9",
"modified": "2024-01-11T09:30:35Z",
"published": "2024-01-11T09:30:35Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-6369"
},
{
"type": "WEB",
"url": "https://plugins.trac.wordpress.org/browser/export-wp-page-to-static-html/trunk/admin/includes/AjaxRequests/cancelRcExportProcess.php#L23"
},
{
"type": "WEB",
"url": "https://plugins.trac.wordpress.org/browser/export-wp-page-to-static-html/trunk/admin/includes/AjaxRequests/deleteExportedZipFile.php#L24"
},
{
"type": "WEB",
"url": "https://plugins.trac.wordpress.org/browser/export-wp-page-to-static-html/trunk/admin/includes/AjaxRequests/exportLogPercentage.php#L23"
},
{
"type": "WEB",
"url": "https://plugins.trac.wordpress.org/browser/export-wp-page-to-static-html/trunk/admin/includes/AjaxRequests/requestForWpPageToStaticHtml.php#L24"
},
{
"type": "WEB",
"url": "https://plugins.trac.wordpress.org/browser/export-wp-page-to-static-html/trunk/admin/includes/AjaxRequests/saveAdvancedSettings.php#L22"
},
{
"type": "WEB",
"url": "https://plugins.trac.wordpress.org/browser/export-wp-page-to-static-html/trunk/admin/includes/AjaxRequests/searchPosts.php#L24"
},
{
"type": "WEB",
"url": "https://plugins.trac.wordpress.org/browser/export-wp-page-to-static-html/trunk/admin/includes/AjaxRequests/seeLogsInDetails.php#L22"
},
{
"type": "WEB",
"url": "https://plugins.trac.wordpress.org/changeset/3002740/export-wp-page-to-static-html"
},
{
"type": "WEB",
"url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/47cb48aa-b556-4f25-ac68-ff0a812972c1?source=cve"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-C2GG-4GQ4-JV5J
Vulnerability from github – Published: 2024-04-10 17:16 – Updated: 2024-04-11 14:33Impact
Parameters of UI extensions are always interpreted as Velocity code and executed with programming rights. Any user with edit right on any document like the user's own profile can create UI extensions. This allows remote code execution and thereby impacts the confidentiality, integrity and availability of the whole XWiki installation.
To reproduce, edit your user profile with the object editor and add a UIExtension object with the following values:
Extension Point ID: org.xwiki.platform.panels.Applications
Extension ID: platform.panels.myFakeApplication
Extension parameters:
label=I got programming right: $services.security.authorization.hasAccess('programming')
target=Main.WebHome
targetQueryString=
icon=icon:bomb
Extension Scope: "Current User".
Save the document and open any document. If an application entry with the text "I got programming right: true" is displayed, the attack succeeded, if the code in "label" is displayed literally, the XWiki installation isn't vulnerable.
Patches
This vulnerability has been patched in XWiki 14.10.19, 15.5.4 and 15.9-RC1.
Workarounds
We're not aware of any workarounds apart from upgrading.
References
- https://jira.xwiki.org/browse/XWIKI-21335
- https://github.com/xwiki/xwiki-platform/commit/171e7c7d0e56deaa7b3678657ae26ef95379b1ea
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "org.xwiki.platform:xwiki-platform-uiextension-api"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.10.19"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "org.xwiki.platform:xwiki-platform-uiextension-api"
},
"ranges": [
{
"events": [
{
"introduced": "15.0-rc-1"
},
{
"fixed": "15.5.4"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "org.xwiki.platform:xwiki-platform-uiextension-api"
},
"ranges": [
{
"events": [
{
"introduced": "15.6-rc-1"
},
{
"fixed": "15.9-rc-1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2024-31997"
],
"database_specific": {
"cwe_ids": [
"CWE-862"
],
"github_reviewed": true,
"github_reviewed_at": "2024-04-10T17:16:53Z",
"nvd_published_at": "2024-04-10T22:15:07Z",
"severity": "CRITICAL"
},
"details": "### Impact\nParameters of UI extensions are always interpreted as Velocity code and executed with programming rights. Any user with edit right on any document like the user\u0027s own profile can create UI extensions. This allows remote code execution and thereby impacts the confidentiality, integrity and availability of the whole XWiki installation.\n\nTo reproduce, edit your user profile with the object editor and add a UIExtension object with the following values:\n```\nExtension Point ID: org.xwiki.platform.panels.Applications\nExtension ID: platform.panels.myFakeApplication\nExtension parameters:\u00a0\nlabel=I got programming right: $services.security.authorization.hasAccess(\u0027programming\u0027)\ntarget=Main.WebHome\ntargetQueryString=\nicon=icon:bomb\nExtension Scope: \"Current User\".\n```\n\nSave the document and open any document. If an application entry with the text \"I got programming right: true\" is displayed, the attack succeeded, if the code in \"label\" is displayed literally, the XWiki installation isn\u0027t vulnerable.\n\n### Patches\nThis vulnerability has been patched in XWiki 14.10.19, 15.5.4 and 15.9-RC1.\n\n### Workarounds\nWe\u0027re not aware of any workarounds apart from upgrading.\n\n### References\n* https://jira.xwiki.org/browse/XWIKI-21335\n* https://github.com/xwiki/xwiki-platform/commit/171e7c7d0e56deaa7b3678657ae26ef95379b1ea\n",
"id": "GHSA-c2gg-4gq4-jv5j",
"modified": "2024-04-11T14:33:26Z",
"published": "2024-04-10T17:16:53Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/xwiki/xwiki-platform/security/advisories/GHSA-c2gg-4gq4-jv5j"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-31997"
},
{
"type": "WEB",
"url": "https://github.com/xwiki/xwiki-platform/commit/171e7c7d0e56deaa7b3678657ae26ef95379b1ea"
},
{
"type": "WEB",
"url": "https://github.com/xwiki/xwiki-platform/commit/1b2574eb966457ca4ef34e557376b8751d1be90d"
},
{
"type": "WEB",
"url": "https://github.com/xwiki/xwiki-platform/commit/56748e154a9011f0d6239bec0823eaaeab6ec3f7"
},
{
"type": "PACKAGE",
"url": "https://github.com/xwiki/xwiki-platform"
},
{
"type": "WEB",
"url": "https://jira.xwiki.org/browse/XWIKI-21335"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "XWiki Platform remote code execution from account through UIExtension parameters"
}
GHSA-C2J5-XC4J-XJMM
Vulnerability from github – Published: 2023-02-08 00:30 – Updated: 2026-04-08 18:32The Wicked Folders plugin for WordPress is vulnerable to authorization bypass due to a missing capability check on the ajax_save_folder function in versions up to, and including, 2.18.16. This makes it possible for authenticated attackers, with subscriber-level permissions and above, to invoke this function and perform actions intended for administrators such as modifying the folder structure maintained by the plugin.
{
"affected": [],
"aliases": [
"CVE-2023-0718"
],
"database_specific": {
"cwe_ids": [
"CWE-862"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-02-08T00:15:00Z",
"severity": "MODERATE"
},
"details": "The Wicked Folders plugin for WordPress is vulnerable to authorization bypass due to a missing capability check on the ajax_save_folder function in versions up to, and including, 2.18.16. This makes it possible for authenticated attackers, with subscriber-level permissions and above, to invoke this function and perform actions intended for administrators such as modifying the folder structure maintained by the plugin.",
"id": "GHSA-c2j5-xc4j-xjmm",
"modified": "2026-04-08T18:32:01Z",
"published": "2023-02-08T00:30:33Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-0718"
},
{
"type": "WEB",
"url": "https://plugins.trac.wordpress.org/browser/wicked-folders/tags/2.18.16/lib/class-wicked-folders-ajax.php"
},
{
"type": "WEB",
"url": "https://plugins.trac.wordpress.org/changeset?sfp_email=\u0026sfph_mail=\u0026reponame=\u0026new=2860994%40wicked-folders%2Ftrunk\u0026old=2805161%40wicked-folders%2Ftrunk\u0026sfp_email=\u0026sfph_mail="
},
{
"type": "WEB",
"url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/2c26d6de-5653-4be8-9526-39b30cb61625"
},
{
"type": "WEB",
"url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/2c26d6de-5653-4be8-9526-39b30cb61625?source=cve"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-C2M8-4GCG-V22G
Vulnerability from github – Published: 2026-05-29 23:01 – Updated: 2026-05-29 23:01Summary
Type: Vertical privilege escalation. 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. 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, with no check that the caller has owner-or-admin privilege, no check that the new role is not higher than the caller's own, and no check that the caller is not silently promoting themselves.
File: src/praisonai-platform/praisonai_platform/api/routes/workspaces.py, lines 115-127; services/member_service.py, lines 55-69; api/deps.py, lines 54-73.
Root cause: require_workspace_member exists with a min_role parameter (deps.py:58) but FastAPI's Depends(require_workspace_member) cannot pass arguments, so every route uses the default "member". The route then passes the URL-supplied user_id and the body-supplied role directly to MemberService.update_role, which contains zero permission checks: it loads the member by composite key and assigns member.role = new_role. A user with the lowest possible privilege ("member") thus sets their own role to "owner" with one HTTP PATCH, completing a member-to-owner privilege escalation in a single request.
Affected Code
File 1: src/praisonai-platform/praisonai_platform/api/routes/workspaces.py, lines 115-127.
@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_workspace_member), # <-- BUG: defaults to min_role="member"; no role gate
session: AsyncSession = Depends(get_db),
):
member_svc = MemberService(session)
member = await member_svc.update_role(workspace_id, user_id, body.role) # <-- writes any role to any member
if member is None:
raise HTTPException(status_code=404, detail="Member not found")
return MemberResponse.model_validate(member)
File 2: src/praisonai-platform/praisonai_platform/services/member_service.py, lines 55-69.
async def update_role(
self,
workspace_id: str,
user_id: str,
new_role: str,
) -> Optional[Member]:
"""Update a member's role."""
if new_role not in VALID_ROLES: # only validates the *value*, not the *caller's right*
raise ValueError(f"Invalid role: {new_role}. Must be one of {VALID_ROLES}")
member = await self.get(workspace_id, user_id)
if member is None:
return None
member.role = new_role # <-- BUG: no caller-role check, no target-vs-caller hierarchy check
await self._session.flush()
return member
File 3: src/praisonai-platform/praisonai_platform/api/deps.py, lines 54-73.
async def require_workspace_member(
workspace_id: str,
user: AuthIdentity = Depends(get_current_user),
session: AsyncSession = Depends(get_db),
min_role: str = "member", # <-- default that no route overrides
) -> AuthIdentity:
member_svc = MemberService(session)
has = await member_svc.has_role(workspace_id, user.id, min_role)
if not has:
raise HTTPException(status_code=403, detail="Not a member of this workspace or insufficient role")
user.workspace_id = workspace_id
return user
Why it's wrong: require_workspace_member was clearly designed to be tunable per-route — the min_role parameter is right there — but Depends(require_workspace_member) in FastAPI cannot pass arguments to a dependency, so every route resolves to the default "member". The author's intent is also evident in MemberService.has_role (member_service.py:80-96), which implements an owner > admin > member hierarchy that this endpoint should be enforcing. The endpoint uses none of it. The VALID_ROLES = {"owner", "admin", "member"} enum check (member_service.py:62) only validates the new role string is recognised, not that the caller has the right to assign it. As a result, a member can write {"role": "owner"} to their own membership row and become owner in one PATCH.
Exploit Chain
- Attacker registers an account and joins (or is invited to) any workspace
Was a "member" (the lowest privilege tier — typically anyone can be added by an owner during onboarding, or self-joins via an invite link). State: attacker has a JWT, is aMember(workspace_id=W, user_id=attacker, role="member"). - Attacker sends
PATCH /workspaces/W/members/<attacker_user_id>withAuthorization: Bearer <attacker_jwt>and body{"role": "owner"}. State: control flow entersupdate_member_role. require_workspace_member(W, attacker)runs. Its defaultmin_role="member"is satisfied because the attacker is a member. The dependency returns the attacker's identity. State: route handler proceeds with no further role gate.MemberService.update_role(W, attacker, "owner")runs.VALID_ROLESaccepts"owner".self.get(W, attacker)returns the attacker's existing member row. The next line,member.role = "owner", mutates the attacker's role in place.await self._session.flush()commits. State: attacker is nowMember(workspace_id=W, user_id=attacker, role="owner").- Attacker re-issues
GET /auth/me(or any owner-gated endpoint) and is now treated as workspace owner. State: full administrative control of the workspace, including the ability to add/remove members, change settings, delete the workspace, and exfiltrate everything via the agent/issue/project/comment IDORs that were filed as separate advisories. - Final state: starting from the lowest workspace privilege, the attacker holds owner of the workspace within one HTTP request. The same primitive also lets the attacker DEMOTE the legitimate owner by sending
PATCH /workspaces/W/members/<owner_user_id>with{"role": "member"}— owner lockout in two requests total.
Security Impact
Severity: sec-critical. CVSS 9.1: network attack, low complexity, low privileges (the lowest tier on the platform), no user interaction, scope changed (the privilege boundary the attacker crosses is the workspace owner, a different security principal), high confidentiality and integrity (full workspace control), no availability claim (the attacker can also DELETE the workspace via the companion delete_workspace advisory, but that is a separate finding).
Attacker capability: with one workspace-member token plus one PATCH request, the attacker becomes workspace owner. From there: add/remove any user as owner, change every workspace setting (including the settings JSON blob), demote the legitimate owner to "member", or chain into the companion delete_workspace advisory to wipe the workspace entirely. In multi-tenant SaaS deployments where any signup yields a member-level account in some default workspace, this is effectively pre-auth.
Preconditions: praisonai-platform is deployed multi-tenant (more than one workspace exists OR the deployment grants member access on signup); the attacker has any membership token in the target workspace.
Differential: source-inspection-verified end-to-end. The asymmetry between require_workspace_member's min_role parameter (which exists, defaults to "member", and is never overridden) and MemberService.has_role's clearly tiered owner > admin > member hierarchy (which exists but is never invoked with anything but the default) is the smoking gun. With the suggested fix below, the route resolves with min_role="owner", the attacker's member-level token fails the gate at the dependency, and the privilege escalation never reaches the service layer.
Suggested Fix
The fix has two parts. First, the route must resolve require_workspace_member with min_role="owner" (or at least "admin"). Second, MemberService.update_role should refuse to set a target's role higher than the caller's own role, so that an admin cannot accidentally produce another owner.
--- a/src/praisonai-platform/praisonai_platform/api/routes/workspaces.py
+++ b/src/praisonai-platform/praisonai_platform/api/routes/workspaces.py
@@ -115,11 +115,16 @@
+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_workspace_member),
+ 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)
Defence-in-depth in the service layer:
--- a/src/praisonai-platform/praisonai_platform/services/member_service.py
+++ b/src/praisonai-platform/praisonai_platform/services/member_service.py
@@ -55,7 +55,7 @@
- async def update_role(self, workspace_id: str, user_id: str, new_role: str) -> Optional[Member]:
+ async def update_role(self, workspace_id: str, caller_id: str, user_id: str, new_role: str) -> Optional[Member]:
"""Update a member's role."""
+ if not await self.has_role(workspace_id, caller_id, "owner"):
+ raise PermissionError("Only owners can update member roles")
if new_role not in VALID_ROLES:
raise ValueError(...)
The companion endpoints add_member, remove_member, delete_workspace, and update_workspace exhibit the same Depends(require_workspace_member) default-min-role pattern and are filed as their own advisories so each gets a separate CVE.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 0.1.2"
},
"package": {
"ecosystem": "PyPI",
"name": "praisonai-platform"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.1.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-47416"
],
"database_specific": {
"cwe_ids": [
"CWE-269",
"CWE-862"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-29T23:01:59Z",
"nvd_published_at": null,
"severity": "CRITICAL"
},
"details": "## Summary\n\n**Type:** Vertical privilege escalation. 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. The handler then calls `MemberService.update_role(workspace_id, user_id, body.role)` which sets the target member\u0027s role to whatever the request body specifies, with no check that the caller has owner-or-admin privilege, no check that the new role is not higher than the caller\u0027s own, and no check that the caller is not silently promoting themselves.\n**File:** `src/praisonai-platform/praisonai_platform/api/routes/workspaces.py`, lines 115-127; `services/member_service.py`, lines 55-69; `api/deps.py`, lines 54-73.\n**Root cause:** `require_workspace_member` exists with a `min_role` parameter (deps.py:58) but FastAPI\u0027s `Depends(require_workspace_member)` cannot pass arguments, so every route uses the default `\"member\"`. The route then passes the URL-supplied `user_id` and the body-supplied `role` directly to `MemberService.update_role`, which contains zero permission checks: it loads the member by composite key and assigns `member.role = new_role`. A user with the lowest possible privilege (\"member\") thus sets their own role to \"owner\" with one HTTP PATCH, completing a member-to-owner privilege escalation in a single request.\n\n## Affected Code\n\n**File 1:** `src/praisonai-platform/praisonai_platform/api/routes/workspaces.py`, lines 115-127.\n\n```python\n@router.patch(\"/{workspace_id}/members/{user_id}\", response_model=MemberResponse)\nasync def update_member_role(\n workspace_id: str,\n user_id: str,\n body: MemberUpdate,\n user: AuthIdentity = Depends(require_workspace_member), # \u003c-- BUG: defaults to min_role=\"member\"; no role gate\n session: AsyncSession = Depends(get_db),\n):\n member_svc = MemberService(session)\n member = await member_svc.update_role(workspace_id, user_id, body.role) # \u003c-- writes any role to any member\n if member is None:\n raise HTTPException(status_code=404, detail=\"Member not found\")\n return MemberResponse.model_validate(member)\n```\n\n**File 2:** `src/praisonai-platform/praisonai_platform/services/member_service.py`, lines 55-69.\n\n```python\nasync def update_role(\n self,\n workspace_id: str,\n user_id: str,\n new_role: str,\n) -\u003e Optional[Member]:\n \"\"\"Update a member\u0027s role.\"\"\"\n if new_role not in VALID_ROLES: # only validates the *value*, not the *caller\u0027s right*\n raise ValueError(f\"Invalid role: {new_role}. Must be one of {VALID_ROLES}\")\n member = await self.get(workspace_id, user_id)\n if member is None:\n return None\n member.role = new_role # \u003c-- BUG: no caller-role check, no target-vs-caller hierarchy check\n await self._session.flush()\n return member\n```\n\n**File 3:** `src/praisonai-platform/praisonai_platform/api/deps.py`, lines 54-73.\n\n```python\nasync def require_workspace_member(\n workspace_id: str,\n user: AuthIdentity = Depends(get_current_user),\n session: AsyncSession = Depends(get_db),\n min_role: str = \"member\", # \u003c-- default that no route overrides\n) -\u003e AuthIdentity:\n member_svc = MemberService(session)\n has = await member_svc.has_role(workspace_id, user.id, min_role)\n if not has:\n raise HTTPException(status_code=403, detail=\"Not a member of this workspace or insufficient role\")\n user.workspace_id = workspace_id\n return user\n```\n\n**Why it\u0027s wrong:** `require_workspace_member` was clearly designed to be tunable per-route \u2014 the `min_role` parameter is right there \u2014 but `Depends(require_workspace_member)` in FastAPI cannot pass arguments to a dependency, so every route resolves to the default `\"member\"`. The author\u0027s intent is also evident in `MemberService.has_role` (member_service.py:80-96), which implements an `owner \u003e admin \u003e member` hierarchy that this endpoint should be enforcing. The endpoint uses none of it. The `VALID_ROLES = {\"owner\", \"admin\", \"member\"}` enum check (member_service.py:62) only validates the *new role string is recognised*, not that the *caller has the right to assign it*. As a result, a member can write `{\"role\": \"owner\"}` to their own membership row and become owner in one PATCH.\n\n## Exploit Chain\n\n1. Attacker registers an account and joins (or is invited to) any workspace `W` as a \"member\" (the lowest privilege tier \u2014 typically anyone can be added by an owner during onboarding, or self-joins via an invite link). State: attacker has a JWT, is a `Member(workspace_id=W, user_id=attacker, role=\"member\")`.\n2. Attacker sends `PATCH /workspaces/W/members/\u003cattacker_user_id\u003e` with `Authorization: Bearer \u003cattacker_jwt\u003e` and body `{\"role\": \"owner\"}`. State: control flow enters `update_member_role`.\n3. `require_workspace_member(W, attacker)` runs. Its default `min_role=\"member\"` is satisfied because the attacker is a member. The dependency returns the attacker\u0027s identity. State: route handler proceeds with no further role gate.\n4. `MemberService.update_role(W, attacker, \"owner\")` runs. `VALID_ROLES` accepts `\"owner\"`. `self.get(W, attacker)` returns the attacker\u0027s existing member row. The next line, `member.role = \"owner\"`, mutates the attacker\u0027s role in place. `await self._session.flush()` commits. State: attacker is now `Member(workspace_id=W, user_id=attacker, role=\"owner\")`.\n5. Attacker re-issues `GET /auth/me` (or any owner-gated endpoint) and is now treated as workspace owner. State: full administrative control of the workspace, including the ability to add/remove members, change settings, delete the workspace, and exfiltrate everything via the agent/issue/project/comment IDORs that were filed as separate advisories.\n6. Final state: starting from the lowest workspace privilege, the attacker holds owner of the workspace within one HTTP request. The same primitive also lets the attacker DEMOTE the legitimate owner by sending `PATCH /workspaces/W/members/\u003cowner_user_id\u003e` with `{\"role\": \"member\"}` \u2014 owner lockout in two requests total.\n\n## Security Impact\n\n**Severity:** sec-critical. CVSS 9.1: network attack, low complexity, low privileges (the lowest tier on the platform), no user interaction, scope changed (the privilege boundary the attacker crosses is the workspace owner, a different security principal), high confidentiality and integrity (full workspace control), no availability claim (the attacker can also DELETE the workspace via the companion `delete_workspace` advisory, but that is a separate finding).\n**Attacker capability:** with one workspace-member token plus one PATCH request, the attacker becomes workspace owner. From there: add/remove any user as owner, change every workspace setting (including the `settings` JSON blob), demote the legitimate owner to \"member\", or chain into the companion `delete_workspace` advisory to wipe the workspace entirely. In multi-tenant SaaS deployments where any signup yields a member-level account in some default workspace, this is effectively pre-auth.\n**Preconditions:** `praisonai-platform` is deployed multi-tenant (more than one workspace exists OR the deployment grants member access on signup); the attacker has any membership token in the target workspace.\n**Differential:** source-inspection-verified end-to-end. The asymmetry between `require_workspace_member`\u0027s `min_role` parameter (which exists, defaults to \"member\", and is never overridden) and `MemberService.has_role`\u0027s clearly tiered `owner \u003e admin \u003e member` hierarchy (which exists but is never invoked with anything but the default) is the smoking gun. With the suggested fix below, the route resolves with `min_role=\"owner\"`, the attacker\u0027s member-level token fails the gate at the dependency, and the privilege escalation never reaches the service layer.\n\n## Suggested Fix\n\nThe fix has two parts. First, the route must resolve `require_workspace_member` with `min_role=\"owner\"` (or at least `\"admin\"`). Second, `MemberService.update_role` should refuse to set a target\u0027s role higher than the caller\u0027s own role, so that an admin cannot accidentally produce another owner.\n\n```diff\n--- a/src/praisonai-platform/praisonai_platform/api/routes/workspaces.py\n+++ b/src/praisonai-platform/praisonai_platform/api/routes/workspaces.py\n@@ -115,11 +115,16 @@\n+def _require_owner(workspace_id: str, user, session):\n+ return require_workspace_member(workspace_id, user, session, min_role=\"owner\")\n+\n @router.patch(\"/{workspace_id}/members/{user_id}\", response_model=MemberResponse)\n async def update_member_role(\n workspace_id: str,\n user_id: str,\n body: MemberUpdate,\n- user: AuthIdentity = Depends(require_workspace_member),\n+ user: AuthIdentity = Depends(_require_owner),\n session: AsyncSession = Depends(get_db),\n ):\n member_svc = MemberService(session)\n+ if not await member_svc.has_role(workspace_id, user.id, \"owner\"):\n+ raise HTTPException(status_code=403, detail=\"Only owners can change member roles\")\n member = await member_svc.update_role(workspace_id, user_id, body.role)\n```\n\nDefence-in-depth in the service layer:\n\n```diff\n--- a/src/praisonai-platform/praisonai_platform/services/member_service.py\n+++ b/src/praisonai-platform/praisonai_platform/services/member_service.py\n@@ -55,7 +55,7 @@\n- async def update_role(self, workspace_id: str, user_id: str, new_role: str) -\u003e Optional[Member]:\n+ async def update_role(self, workspace_id: str, caller_id: str, user_id: str, new_role: str) -\u003e Optional[Member]:\n \"\"\"Update a member\u0027s role.\"\"\"\n+ if not await self.has_role(workspace_id, caller_id, \"owner\"):\n+ raise PermissionError(\"Only owners can update member roles\")\n if new_role not in VALID_ROLES:\n raise ValueError(...)\n```\n\nThe companion endpoints `add_member`, `remove_member`, `delete_workspace`, and `update_workspace` exhibit the same `Depends(require_workspace_member)` default-min-role pattern and are filed as their own advisories so each gets a separate CVE.",
"id": "GHSA-c2m8-4gcg-v22g",
"modified": "2026-05-29T23:01:59Z",
"published": "2026-05-29T23:01:59Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-c2m8-4gcg-v22g"
},
{
"type": "PACKAGE",
"url": "https://github.com/MervinPraison/PraisonAI"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "praisonai-platform: Any workspace member can promote themselves or others to owner via PATCH /workspaces/{id}/members/{user_id}"
}
GHSA-C2M9-HPP2-J675
Vulnerability from github – Published: 2024-12-13 15:30 – Updated: 2026-04-28 21:35Missing Authorization vulnerability in Wiser Notify WiserNotify Social Proof allows Exploiting Incorrectly Configured Access Control Security Levels.This issue affects WiserNotify Social Proof: from n/a through 2.5.
{
"affected": [],
"aliases": [
"CVE-2023-41690"
],
"database_specific": {
"cwe_ids": [
"CWE-862"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-12-13T15:15:23Z",
"severity": "MODERATE"
},
"details": "Missing Authorization vulnerability in Wiser Notify WiserNotify Social Proof allows Exploiting Incorrectly Configured Access Control Security Levels.This issue affects WiserNotify Social Proof: from n/a through 2.5.",
"id": "GHSA-c2m9-hpp2-j675",
"modified": "2026-04-28T21:35:26Z",
"published": "2024-12-13T15:30:42Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-41690"
},
{
"type": "WEB",
"url": "https://patchstack.com/database/wordpress/plugin/wiser-notify/vulnerability/wordpress-wisernotify-social-proof-plugin-2-5-broken-access-control-vulnerability?_s_id=cve"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-C2QP-GP7H-J46P
Vulnerability from github – Published: 2022-05-24 17:13 – Updated: 2023-05-23 15:30The Rank Math plugin through 1.0.40.2 for WordPress allows unauthenticated remote attackers to update arbitrary WordPress metadata, including the ability to escalate or revoke administrative privileges for existing users via the unsecured rankmath/v1/updateMeta REST API endpoint.
{
"affected": [],
"aliases": [
"CVE-2020-11514"
],
"database_specific": {
"cwe_ids": [
"CWE-269",
"CWE-862"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2020-04-07T17:15:00Z",
"severity": "HIGH"
},
"details": "The Rank Math plugin through 1.0.40.2 for WordPress allows unauthenticated remote attackers to update arbitrary WordPress metadata, including the ability to escalate or revoke administrative privileges for existing users via the unsecured rankmath/v1/updateMeta REST API endpoint.",
"id": "GHSA-c2qp-gp7h-j46p",
"modified": "2023-05-23T15:30:25Z",
"published": "2022-05-24T17:13:34Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-11514"
},
{
"type": "WEB",
"url": "https://rankmath.com/changelog"
},
{
"type": "WEB",
"url": "https://wordpress.org/plugins/seo-by-rank-math/#developers"
},
{
"type": "WEB",
"url": "https://www.wordfence.com/blog/2020/03/critical-vulnerabilities-affecting-over-200000-sites-patched-in-rank-math-seo-plugin"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-C2R4-2V2X-5WFJ
Vulnerability from github – Published: 2025-04-04 18:31 – Updated: 2026-04-28 21:35Missing Authorization vulnerability in Dimitri Grassi Salon booking system allows Exploiting Incorrectly Configured Access Control Security Levels. This issue affects Salon booking system: from n/a through 10.10.7.
{
"affected": [],
"aliases": [
"CVE-2025-32220"
],
"database_specific": {
"cwe_ids": [
"CWE-862"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-04-04T16:15:31Z",
"severity": "MODERATE"
},
"details": "Missing Authorization vulnerability in Dimitri Grassi Salon booking system allows Exploiting Incorrectly Configured Access Control Security Levels. This issue affects Salon booking system: from n/a through 10.10.7.",
"id": "GHSA-c2r4-2v2x-5wfj",
"modified": "2026-04-28T21:35:34Z",
"published": "2025-04-04T18:31:02Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-32220"
},
{
"type": "WEB",
"url": "https://patchstack.com/database/wordpress/plugin/salon-booking-system/vulnerability/wordpress-salon-booking-system-plugin-10-10-7-broken-access-control-vulnerability?_s_id=cve"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:L",
"type": "CVSS_V3"
}
]
}
Mitigation
- Divide the product into anonymous, normal, privileged, and administrative areas. Reduce the attack surface by carefully mapping roles with data and functionality. Use role-based access control (RBAC) [REF-229] to enforce the roles at the appropriate boundaries.
- Note that this approach may not protect against horizontal authorization, i.e., it will not protect a user from attacking others with the same role.
Mitigation
Ensure that access control checks are performed related to the business logic. These checks may be different than the access control checks that are applied to more generic resources such as files, connections, processes, memory, and database records. For example, a database may restrict access for medical records to a specific database user, but each record might only be intended to be accessible to the patient and the patient's doctor [REF-7].
Mitigation MIT-4.4
Strategy: Libraries or Frameworks
- Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.
- For example, consider using authorization frameworks such as the JAAS Authorization Framework [REF-233] and the OWASP ESAPI Access Control feature [REF-45].
Mitigation
- For web applications, make sure that the access control mechanism is enforced correctly at the server side on every page. Users should not be able to access any unauthorized functionality or information by simply requesting direct access to that page.
- One way to do this is to ensure that all pages containing sensitive information are not cached, and that all such pages restrict access to requests that are accompanied by an active and authenticated session token associated with a user who has the required permissions to access that page.
Mitigation
Use the access control capabilities of your operating system and server environment and define your access control lists accordingly. Use a "default deny" policy when defining these ACLs.
CAPEC-665: Exploitation of Thunderbolt Protection Flaws
An adversary leverages a firmware weakness within the Thunderbolt protocol, on a computing device to manipulate Thunderbolt controller firmware in order to exploit vulnerabilities in the implementation of authorization and verification schemes within Thunderbolt protection mechanisms. Upon gaining physical access to a target device, the adversary conducts high-level firmware manipulation of the victim Thunderbolt controller SPI (Serial Peripheral Interface) flash, through the use of a SPI Programing device and an external Thunderbolt device, typically as the target device is booting up. If successful, this allows the adversary to modify memory, subvert authentication mechanisms, spoof identities and content, and extract data and memory from the target device. Currently 7 major vulnerabilities exist within Thunderbolt protocol with 9 attack vectors as noted in the Execution Flow.