Conversation
Closes GHSA-g2hc-wmw2-32jr. The deleteSnapshot service method was performing no authorization check, allowing any authenticated user to delete snapshots belonging to applications they do not own or have access to (BOLA/IDOR vulnerability). Fix mirrors the existing restoreSnapshot pattern in the same class: resolve the application via applicationService.findById with getEditPermission() before executing the delete, returning NO_RESOURCE_FOUND to the caller when permission is absent. Also updates the deleteSnapshot happy-path test to run under a real user context with an owned application, and adds a regression test that asserts the error is returned for an inaccessible application ID.
WalkthroughBoth Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant AppSnapshotService as SnapshotService
participant ApplicationService as AppService
participant SnapshotRepo as SnapshotRepository
Client->>SnapshotService: deleteSnapshot(branchedApplicationId)
SnapshotService->>AppService: findById(branchedApplicationId, EDIT)
AppService-->>SnapshotService: Application (or NOT_FOUND)
alt Application found
SnapshotService->>SnapshotRepo: deleteByApplicationId(application.id)
SnapshotRepo-->>SnapshotService: delete result
SnapshotService-->>Client: success
else Not found / no access
AppService-->>SnapshotService: NO_RESOURCE_FOUND
SnapshotService-->>Client: error (NO_RESOURCE_FOUND)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationSnapshotServiceTest.java`:
- Around line 299-320: The test deleteSnapshot_WhenUserHasNoAccess_ThrowsError
currently uses a randomAppId so it only exercises the “missing resource” path;
instead, create and persist a real Application owned by the other user (the one
set up in `@BeforeEach`, e.g. the api_user context) and capture its id, then
switch to the `@WithUserDetails`("usertest@usertest.com") context and call
applicationSnapshotService.deleteSnapshot(existingAppId) to verify it produces
AppsmithError.NO_RESOURCE_FOUND for FieldName.APPLICATION; update the test to
use the persisted application's id (not a random id) and keep the
StepVerifier.expectErrorMatches assertion against
AppsmithError.NO_RESOURCE_FOUND.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2921429d-6ec5-4dfc-9367-a36b802a2523
📒 Files selected for processing (2)
app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationSnapshotServiceCEImpl.javaapp/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationSnapshotServiceTest.java
...psmith-server/src/test/java/com/appsmith/server/services/ApplicationSnapshotServiceTest.java
Show resolved
Hide resolved
…rove tests Adds the missing authorization check to getWithoutDataByBranchedApplicationId, which was querying snapshot metadata directly from the repository without verifying the caller's permission on the application (the existing comment claimed a permission check but the code never performed one). Uses applicationPermission.getReadPermission() (READ_APPLICATIONS) since this is a read-only operation, mirroring the edit-permission pattern already applied to deleteSnapshot and restoreSnapshot. Also cleans up the deleteSnapshot no-access regression test (removes dead code for an Application object that was created but never persisted) and adds a matching regression test for the GET endpoint. All four snapshot operations now enforce authorization consistently: - create → MANAGE_APPLICATIONS (via exportService) - restore → MANAGE_APPLICATIONS (explicit) - delete → MANAGE_APPLICATIONS (explicit) - get → READ_APPLICATIONS (explicit, added here)
… (GHSA-g2hc-wmw2-32jr) (#41624) ## Description Fixes a Broken Object-Level Authorization (BOLA/IDOR) vulnerability in the application snapshot deletion endpoint (GHSA-g2hc-wmw2-32jr). **Root cause:** `ApplicationSnapshotServiceCEImpl.deleteSnapshot` was calling `applicationSnapshotRepository.deleteAllByApplicationId` directly without performing any authorization check. Any authenticated user who knew a target application ID could send `DELETE /api/v1/applications/snapshot/{appId}` and successfully destroy that application's snapshots — including snapshots belonging to other users and tenants. **Fix:** Mirror the existing `restoreSnapshot` pattern in the same class. Resolve the application via `applicationService.findById(id, applicationPermission.getEditPermission())` before executing the delete. When the caller does not have edit permission on the application, `findById` returns empty, which triggers `switchIfEmpty` and returns `NO_RESOURCE_FOUND` to the caller — identical behavior to all other protected operations in this service. **Changes:** - `ApplicationSnapshotServiceCEImpl.java`: 5-line change to `deleteSnapshot` — permission check added, no interface or API signature changes - `ApplicationSnapshotServiceTest.java`: Updated existing `deleteSnapshot` happy-path test to run under a real user + owned application; added new regression test `deleteSnapshot_WhenUserHasNoAccess_ThrowsError` asserting that an inaccessible app ID returns `AppsmithError.NO_RESOURCE_FOUND` Fixes https://linear.app/appsmith/issue/APP-15032/high-broken-object-level-authorization-allows-non-owner-to-delete ## Automation /ok-to-test tags="@tag.All" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/23285869385> > Commit: e4911c0 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=23285869385&attempt=2" target="_blank">Cypress dashboard</a>. > Tags: `@tag.All` > Spec: > <hr>Thu, 19 Mar 2026 09:54:26 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Snapshot read and delete actions now validate application existence and user permissions before proceeding; unauthorized access returns a clear error. * **Tests** * Added tests covering access control for snapshot deletion and snapshot read-without-data to assert proper error handling for users without access. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Description
Fixes a Broken Object-Level Authorization (BOLA/IDOR) vulnerability in the application snapshot deletion endpoint (GHSA-g2hc-wmw2-32jr).
Root cause:
ApplicationSnapshotServiceCEImpl.deleteSnapshotwas callingapplicationSnapshotRepository.deleteAllByApplicationIddirectly without performing any authorization check. Any authenticated user who knew a target application ID could sendDELETE /api/v1/applications/snapshot/{appId}and successfully destroy that application's snapshots — including snapshots belonging to other users and tenants.Fix: Mirror the existing
restoreSnapshotpattern in the same class. Resolve the application viaapplicationService.findById(id, applicationPermission.getEditPermission())before executing the delete. When the caller does not have edit permission on the application,findByIdreturns empty, which triggersswitchIfEmptyand returnsNO_RESOURCE_FOUNDto the caller — identical behavior to all other protected operations in this service.Changes:
ApplicationSnapshotServiceCEImpl.java: 5-line change todeleteSnapshot— permission check added, no interface or API signature changesApplicationSnapshotServiceTest.java: Updated existingdeleteSnapshothappy-path test to run under a real user + owned application; added new regression testdeleteSnapshot_WhenUserHasNoAccess_ThrowsErrorasserting that an inaccessible app ID returnsAppsmithError.NO_RESOURCE_FOUNDFixes https://linear.app/appsmith/issue/APP-15032/high-broken-object-level-authorization-allows-non-owner-to-delete
Automation
/ok-to-test tags="@tag.All"
🔍 Cypress test results
Tip
🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
Workflow run: https://github.com/appsmithorg/appsmith/actions/runs/23285869385
Commit: e4911c0
Cypress dashboard.
Tags:
@tag.AllSpec:
Thu, 19 Mar 2026 09:54:26 UTC
Communication
Should the DevRel and Marketing teams inform users about this change?
Summary by CodeRabbit
Bug Fixes
Tests