From 00b94d36a8f03c0620665bce443aa802db45d79f Mon Sep 17 00:00:00 2001 From: Manish Gupta Date: Mon, 27 Jul 2026 12:59:47 +0530 Subject: [PATCH] [WEB-8401] test: add unauthorized PATCH regression coverage (CodeRabbit #9483) The suite covered delete/restore/rebind but not PATCH (also scoped to created_by=request.user). Add an attacker PATCH asserting 404 + unchanged attributes so the PATCH ownership filter can't silently regress. Fail-before verified. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../app/test_space_asset_mutation_scope_app.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apps/api/plane/tests/contract/app/test_space_asset_mutation_scope_app.py b/apps/api/plane/tests/contract/app/test_space_asset_mutation_scope_app.py index 1777f08754..263577f61e 100644 --- a/apps/api/plane/tests/contract/app/test_space_asset_mutation_scope_app.py +++ b/apps/api/plane/tests/contract/app/test_space_asset_mutation_scope_app.py @@ -118,6 +118,21 @@ class TestSpaceAssetMutationScope: asset.refresh_from_db() assert asset.comment_id == original_comment, "Another user's asset was rebound" + def test_attacker_cannot_patch_others_asset(self, workspace, project, board, owner): + asset = _asset(workspace, project, owner) + original_attributes = dict(asset.attributes) + attacker = _user("attacker") + response = _client(attacker).patch( + DELETE_URL.format(anchor=board.anchor, pk=asset.id), + {"attributes": {"name": "tampered.pdf"}}, + format="json", + ) + assert response.status_code == status.HTTP_404_NOT_FOUND, ( + f"Got {response.status_code}: {getattr(response, 'data', None)!r}" + ) + asset.refresh_from_db() + assert asset.attributes == original_attributes, "Another user's asset attributes were modified" + def test_owner_can_delete_own_asset(self, workspace, project, board, owner): """Positive control: the asset's creator may delete it.""" asset = _asset(workspace, project, owner)