mirror of
https://github.com/makeplane/plane.git
synced 2026-09-02 03:59:00 +02:00
Both new create-asset and duplicate-asset paths accepted a request that
simply omitted project_id and silently stored project_id=None on the
row. is_project_accessible_to() treats project_id=None as
workspace-accessible-by-default (the correct behavior for genuinely
workspace-level assets like logos), so an attacker could reuse that
fallback to erase the project-membership check this PR just added,
defeating its own goal for the exact entity types it targets.
GenericAssetEndpoint.post always creates an ISSUE_ATTACHMENT, a
project-scoped entity type, so project_id is now required before the
row is created (400 if missing); the dedup-echo short-circuit above it
is unaffected since it never creates a row.
DuplicateAssetEndpoint.post now defaults project_id to the source
asset's own project when the request omits it (or sends it empty/null)
instead of defaulting to None -- the caller's access to the source was
only ever established through that project, and a duplicate belongs to
the same project as its source by construction rather than by
client-supplied opinion. Explicitly naming a different destination
project is unaffected and still goes through the existing
membership check.
Also aligned the destination-project error response shape in
DuplicateAssetEndpoint with GenericAssetEndpoint's ({"error": ...,
"status": False}), which had drifted between the two hand-duplicated
checks.
Co-authored-by: Plane AI <noreply@plane.so>